Its really wild, as a person coming from other languages who has written maybe ten lines of C in his life that the functions that seem to be massive footguns in C are, like, "format a string" or "get time in GMT." That's... really scary.
gmtime is just not thread-safe that's all, since it returns a static structure; gmtime_r is not banned.
Git's list of banned C functions
211–220 of 639 posts
Re: Git's list of banned C functions
#212Earlier quoted context omitted.
For reasons that were never clearly articulated, the prefix approach was considered odd, backwards, and to have numerous downsides, at least where I learned C. In hindsight, I can only cringe at that attitude. Strings as added in later Pascal, about 40 years ago now, were memory safe in a way that C strings still are not.
The prefix approach turns the neat "strings are just character arrays are just pointers" pattern into something a lot more clunky, because now you've got this really basic data type that is actually a struct and now you have to have an opinion on how wide the length value is and short strings get a lot of memory overhead in just lengths, and so on. In hindsight, I think the complexity is worth the safety, but I could…
Human concepts are inherently messy. "Elegant" solutions just shove the mess down the road.
Re: Git's list of banned C functions
#213However, I look at old books on C, and then I look at this list, and I wonder if it would not have been helpful to, after mentioning that a function was banned, suggest what the replacement is, even as a comment.
Re: Git's list of banned C functions
#214Earlier quoted context omitted.
That assumes you have a header, which only exists at compile time for the developer. The running program knows nothing about it.
Why would a program need to know (e.g.) the details of what system calls or stdlib functions that a procedure it invokes uses? Aren’t C functions pretty well separated from each other except for the odd signal handler and assuming a stable ABI? In my view most of the issues with C are semantics within the function blocks.
Re: Git's list of banned C functions
#215To respond to some of the comments. It is not that there is anything intrinsically wrong with these functions. You can technically use all of them and I have been using all of them, safely, for decades. The issue is they are huge traps to the point that in a larger piece of software one can say "well, it's just not worth it". You can go much, much, much further than that. In couple embedded projects I worked some of…
Except when you have these rules in Java, the ironic counter-point is "if you are doing this much memory control yourself, you should just use C or C++ or something".
I'll keep your comment in mind next time I see that rebuttal. Thank you.
Re: Git's list of banned C functions
#216Earlier quoted context omitted.
The decision to make C strings null terminated with implied length instead of length + blob continues to trip us up, 30+ years later. There's a good reason the "safe" versions of those functions all take length parameters. But way back when this approach was chosen, I don't think the state of the art could fully predict this outcome. But also, "strings" and "time" are actually very complex concepts, and these functio…
For reasons that were never clearly articulated, the prefix approach was considered odd, backwards, and to have numerous downsides, at least where I learned C. In hindsight, I can only cringe at that attitude. Strings as added in later Pascal, about 40 years ago now, were memory safe in a way that C strings still are not.
Re: Git's list of banned C functions
#217To respond to some of the comments. It is not that there is anything intrinsically wrong with these functions. You can technically use all of them and I have been using all of them, safely, for decades. The issue is they are huge traps to the point that in a larger piece of software one can say "well, it's just not worth it". You can go much, much, much further than that. In couple embedded projects I worked some of…
How often does the dynamic allocation rule lead to an ad-hoc allocator appearing inside the program? Also doesn’t the OS lie? I thought the memory wasn’t really physically assigned until first use.
In both cases the project size is small enough, or the scrutiny is high enough that the ad-hoc allocator doesn't develop. The environment is also simple enough that the memory cheats you're thinking of don't exist (or you can squash them by touching all allocated memory up front).
Re: Git's list of banned C functions
#218Earlier quoted context omitted.
strncpy() is not a "safer" strcpy(). It can avoid some errors involving writing past the end of the target array ( if you tell it the correct length for that array), but it's not a true string function, and it can leave the target unterminated and therefore not a valid string. http://the-flat-trantor-society.blogspot.com/2012/03/no-strn...
I never could really understand the point of strncpy()... we always end up wrapping to deal with writing an unterminated string. Was it intended for fixed length records?
Re: Git's list of banned C functions
#219Earlier quoted context omitted.
Still, unless you're writing something that has to be very low-level all the way through, it's better to use a string-handling library than the stdlib tools for strings.
The first thing you do is not use any strings . You'll be amazed how much you can get done in languages that aren't so obsessively centered around stringified programming.
When handling strings in C, it's useful to use the string functions from glib or pull in one of the specifically safe string handling libraries and not use any C stdlib functions for strings at all.
There are a number of C strings libraries safer to use than the standard library, and many of them are simpler, more feature-rich, or both.
* https://github.com/intel/safestringlib (MIT licensed)
* https://github.com/rurban/safeclib (MITish)
* https://github.com/mpedrero/safeString (MIT licensed)
* https://github.com/antirez/sds (BSD 2-clause, and gives you dynamic strings)
* https://github.com/maxim2266/str (BSD 3-clause)
* https://github.com/xyproto/egcc (GPL 2.0, includes GC on strings)
* https://github.com/composer927/stringstruct (GPL 3.0)
* https://github.com/c-factory/strings (MIT licensed)
* https://github.com/cavaliercoder/c-stringbuilder (MIT licensed, does dynamic)
If one does use the C standard library directly for handling strings, the advisories from CERT, NASA, Github, and others should be welcome advice (CERT's advice, BTW, includes recommending a safer strings library right off).
Re: Git's list of banned C functions
#220Earlier quoted context omitted.
The decision to make C strings null terminated with implied length instead of length + blob continues to trip us up, 30+ years later. There's a good reason the "safe" versions of those functions all take length parameters. But way back when this approach was chosen, I don't think the state of the art could fully predict this outcome. But also, "strings" and "time" are actually very complex concepts, and these functio…
For reasons that were never clearly articulated, the prefix approach was considered odd, backwards, and to have numerous downsides, at least where I learned C. In hindsight, I can only cringe at that attitude. Strings as added in later Pascal, about 40 years ago now, were memory safe in a way that C strings still are not.
cat_pascal_strings(pascalstr *uninited_memory,
pascalstr *left,
pascalstr *right);
how big is uninited_memory? Can left and right fit into it?You need to design language constructs around Pascal srings to make them actually safe. Such as, oh, make it impossible to have an uninitialized such object. The object has o know both its allocation size and the actual size of the string stored in it.
What is unsafe is constructing new objects in an anonymous block of memory that knows nothing about its size.
C programs run aground there not just with strings!
struct foo *ptr = malloc(sizeof ptr); // should be sizeof *ptr!!
if (ptr) {
ptr->name = name;
ptr->frobosity = fr;
Oops! The wrong size of allocated only the size of a pointer: 4 or 8 bytes, typically nowadays, but the structure is 48 bytes wide."struct foo" itself isn't inferior to a Pascal RECORD; the problem is coming from the wild and loose allocation side of things.
Working with strings in Pascal is relatively safe, but painfully limiting. It's a dead end. You can't build anything on top of it. Can you imagine trying to make a run-time for a high level language in Pascal? You need to be in the driver's seat regarding how strings work.