Earlier quoted context omitted.
> I actually studied Phisolophy/Logic at Uni. Good try though. Appeal to authority. PS: I studied philosophy too.
Nope. Wrong again. You should probably take that class again. I am telling you that I evaluated your claim, I didn’t google it or ask ChatGPT.
C Strings and my slow descent to madness
311–320 of 329 posts
Re: C Strings and my slow descent to madness
#312Earlier quoted context omitted.
> what happens in the case where the source string is not properly NULL terminated That’s not a string.
None of strlcpy, strncpy, and strcpy will know that you have not provided a string. They will assume the source pointer is a string and as such, will read (and write, in the case of strcpy) bytes until they find that NUL. This is the upside of strlcpy. Whatever is in your output buffer is guaranteed to be a NUL terminated and have your desired length. strncpy does not make that guarantee. strcpy will give you somethi…
Re: C Strings and my slow descent to madness
#313Earlier quoted context omitted.
It’s in the other direction, snprintf(small_buf, small_size, “%s”, huge_string) will need to iterate the whole string.
why? snprintf() will just write as many bytes from huge_string as necessary, up to the smaller of small_size and strlen (huge_string). what makes you believe it will iterate the whole of huge_string?
> The snprintf function returns the number of characters that would have been written had n been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred.
In essence it needs to return strlen of huge_string even though very little of it was actually written.
Re: C Strings and my slow descent to madness
#314Earlier quoted context omitted.
Automatic memory management makes copies?
No. Another word for automatic memory management is garbage collection.
Re: C Strings and my slow descent to madness
#315Earlier quoted context omitted.
why? snprintf() will just write as many bytes from huge_string as necessary, up to the smaller of small_size and strlen (huge_string). what makes you believe it will iterate the whole of huge_string?
Quoth the standard: > The snprintf function returns the number of characters that would have been written had n been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred. In essence it needs to return strlen of huge_string even though very little of it was actually written.
> Attention: In versions of the GNU C Library prior to 2.1 the return value is the number of characters stored, not including the terminating null; unless there was not enough space in s to store the result in which case -1 is returned. This was changed in order to comply with the ISO C99 standard.
ISO C99 needs a kick in the head. Yes, there is a use case for this return value (buffer wasn't large enough, reallocate and try it again). But wow, own goal team!
Thanks for this. I had no idea that C99 had defined this so stupidly. I do see that in 2004, the linux kernel added replacements (scnprintf() which behave as the pre-C99 versions of snprintf generally did). There's a good discussion of this here: https://lwn.net/Articles/69419/
Re: C Strings and my slow descent to madness
#316Earlier quoted context omitted.
That was my point. Although you can, actually - since literals themselves are array-typed, you can sizeof them to get the character count without relying on null termination. It's even possible to get a non-null-terminated literal if the target array type is not large enough to fit null, e.g.: char s[3] = "foo"; // not null-terminated!
> character count Byte count.
Re: C Strings and my slow descent to madness
#317Re: C Strings and my slow descent to madness
#318Earlier quoted context omitted.
None of strlcpy, strncpy, and strcpy will know that you have not provided a string. They will assume the source pointer is a string and as such, will read (and write, in the case of strcpy) bytes until they find that NUL. This is the upside of strlcpy. Whatever is in your output buffer is guaranteed to be a NUL terminated and have your desired length. strncpy does not make that guarantee. strcpy will give you somethi…
Passing something that is not a string to strcpy or strlcpy is undefined behavior. They operate on strings, which are null-terminated by definition. On the flip side, strncpy operates on character arrays, which do not have to be null-terminated. (This is also why the output buffer is not always null-terminated: it's not meant to represent a string, despite the highly confusing str- prefix.)
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
size_t strlcpy(char *dest, const char *src, size_t size);
From that, how do you know that strncpy expects and produces a character array, strcpy expects and produces a string, and strlcpy takes either a character array or string and produces a string?Your descriptions of the string/character copy functions are factual and accurate. But correct use depends on programmer understanding. You do not get any runtime guarantee. And IME, when you are under a deadline, 13 function calls and 3 message queues deep in some ancient codebase, while trying to get a non-trivial feature working, the distinction between a character array and a string is easily forgotten.
Anyways, my assertions are:
1) Using C for strings is a poor choice 2) If your compiler vendor or cranky boss forces use of C, use strlcpy to handle string copying.
Re: C Strings and my slow descent to madness
#319Pop quiz, which of these is safe, given "char buf[80]" and arbitrary user input in argv[1]? gets(buf); scanf("%s", buf); strcpy(buf, argv[1]); scanf("%80s", buf); strncpy(buf, argv[1], 80); snprintf(buf, 80, argv[1]); ---- The delightful answer is none of them . The first three have no bounds checking at all, meaning that they will happily overflow the buffer to an arbitrary extent (gets, at least, will usually trigg…
> The delightful answer is none of them. No. Sorry. This is bad programming. C'mon. I started programming back in the 8080, 8085, 6502, etc. days. I had to program some prototype computers using a hex keypad while entering raw machine code (not even assembler). I still own a couple of these: https://i.imgur.com/ZsIJj1p.png In a couple of cases I had to take this approach to bootstrap Forth on a 6502, then write a ful…
On the other hand, not everyone had that luck. I've seen a good number of people that are very good at what they do but lack more general culture. But it's hard to keep up with everything. Software is a huge world, I think already way too big for everyone to know everything. And it's not just software too, it's important to learn about business too, and maybe a bit of maths here and there isn't a bad idea, and there's also the hardware part, networking, and every day there is more and more and more.
What I mean by this is that I don't know how things were before, but today, for a lot of people that write code, it's not possible to know everything, have everything fit inside your head. In those cases, people usually start asking for more guardrails in their tools, because they're no longer manipulated only by experts. And sometimes the experts themselves ask for guardrails too. So some want tools to change, others don't want them to change, and both have a point.
On one hand, I understand that blaming the tool isn't a good attitude to have. On the other hand, my job consists in building tools for other professionals, and I feel like I have way higher standards for the tools that I produce compared to the tools that I use.
Re: C Strings and my slow descent to madness
#320Earlier quoted context omitted.
> The delightful answer is none of them. No. Sorry. This is bad programming. C'mon. I started programming back in the 8080, 8085, 6502, etc. days. I had to program some prototype computers using a hex keypad while entering raw machine code (not even assembler). I still own a couple of these: https://i.imgur.com/ZsIJj1p.png In a couple of cases I had to take this approach to bootstrap Forth on a 6502, then write a ful…
I did start with C at university, C and Scheme. We didn't go very in depth in the "defensive programming" part, especially with C. We talked a bit about safety when we were doing web and database stuff, but I think that's it. I am pretty lucky, one of my friend is in cybersecurity, another is very good with C, and there are lots of people online freely sharing their knowledge, so at least I kind of know what I don't…
I think your view is of this is reasonably balanced. There is that element of someone without extensive experience not knowing what they don't know.
Well, can we blame them for that?
Thirty years ago, probably not. Today, I think the answer could be yes. A few days of time well spent web searching, reading and watching videos can bring someone from complete ignorance of a subject to having a very good starting point from which to grow. Today there's information on almost anything anyone might want to learn, free and widely available. What, generally speaking isn't widely present is the willingness and dedication to learn.
I have friends my age who stopped learning twenty years ago, maybe even sooner. They just don't care enough. Or maybe they thought they were safe and did not need to. In at least one case I know, that was a huge mistake. He started life as a field service engineer with great prospects. He never bothered to learn anything new. Today he sits in a trailer at an oil field 24/7 manually logging various pressures and temperatures multiple times a day.
I also blame the educational system for some of this. Maybe I was fortunate to have gone to school when I did. We started with assembler. Actually, machine language, raw 1's and 0's. By the time I learned C I had designed a few industrial control computers and fully coded them in assembler. The transition to C was very easy. And nobody had to tell me where the dangers were...because, coming from assembler, it was obvious.