simple C program using bind() worked on 9.3 doesn't work on 11.4

Strictly speaking, this an API contract violation. However, since use-after-free as often referred to in that manner*, I don't think this is much of a stretch either. In other words, I'm just being slightly lazy. This doesn't make the issue any less real.

* From OpenBSD man pages, https://man.openbsd.org/free.3:

Like i said in my edit, after reading the notes section of pthread_join it's pretty clear that the problem is the programmer of the crashing application ignoring the documentation. Undefined behavior is something you don't invoke unless you know some way to make it defined or have a very serious reason to rely on it. He/she/it didn't and it blew up.

The comparison is fine. Actually i would have brought up free myself if you wouldn't have beat me to it. It's just that those kind of problems are very much unavoidable unless you take memory management out of the programmers hands (i think that's what rust does?) or have some more or less clever logic to check the validity of the requested operation. All of that comes with it's own set of drawbacks that depending on the situation might or might not be acceptable.

It's also not even that taking memory management out of the equation would fully eliminate such problems. An api can only reasonably have safety nets for so much usage that does not make any practical sense before it becomes bloated and slow just to safe the world from people who ignore documentation. It's kinda like expecting a second call to strtok to return the same string again even if the documentation says you get the next one just because when you tried your string happened to contain the same token in a row two times.

Who cares about me? I don't even have source code access for that shit. (Which technically makes all behavior well defined, since everything is already compiled.)

I am sorry, the "you" in that sentence was meant in a general sense. It was not my intention to refer to you personally. I just wanted to say that if one is writing C it has to accepted that unchecked memory management is part of the package. Sometimes that will be advantageous. Sometimes it will be a waste of time and an unneeded possibility for errors.
 
Like i said in my edit, after reading the notes section of pthread_join it's pretty clear that the problem is the programmer of the crashing application ignoring the documentation. Undefined behavior is something you don't invoke unless you know some way to make it defined or have a very serious reason to rely on it. He/she/it didn't and it blew up.
Good points.

In a software development environment "undefined behavior" is something you plan to avoid. Over the years I've seen many techniques to avoid, for example, double free. In essence, the attempt is to prevent complacency and laziness from slipping into code. Most work real well. That's the beauty of C, you can implement what you want to prevent this potential problem. It is up to you.

A case in point is to look at the OpenVMS systems code. The use of descriptors to control access to functions takes more work but protects the system.

Some of the mish-mash code and programming I've seen has boggled me. If people want to write C then learn the language and UNDERSTAND IT.
If it's too hard for you (in a general sense), then please, program in a more controlled language.

Finally, mistakes are made, but good code auditing will find them.
 
In fact, this is legal in C:
Code:
int i; char* c; char x;
....

x=i[c];
 
boy do I hate *argv[]. **argv looks more intuitive.
If you think that's bad, you'd love the book Modern C (there's a link to a 20-chapter free PDF version). While technically correct, the conventions it uses still look strange to me:
Code:
int main(int argc, char* argv[argc+1])

char* strcpy(char dst[restrict static 1], char const src[restrict static 1])
If a function parameter is declared with the form T v[static 1], pass (void*)0 as that parameter in a call to that function and observe how Clang's -Wnonnull flag works for just that one case and not 0, 0UL, (int*)0, etc. I'm not saying it's a useless flag, but considering it only catches one specific case…

The standard NULL macro (with no single standard value) is discouraged as well. Apparently, some systems exist where NULL is defined to be a zero-valued integer literal of type T (e.g. 0, 0UL) and sizeof(T) < sizeof(void*), which can result in program crashes when passing NULL to variadic functions that expect pointers like printf(3) with certain format specifications and execl(3).

I also get the feeling that the author would have preferred this declaration of fgets(3) instead:
Code:
char* fgets(size_t n, char buf[restrict n], FILE* restrict stream);

C's syntax is confusing to a lot of people, and I'm honestly not sure if the conventions in the book make it better or worse.
 
C's syntax is confusing to a lot of people, and I'm honestly not sure if the conventions in the book make it better or worse.
I'm not familiar with books published by Manning Publications. Thanks for quoting from that book, now I understand why their books cover are so creepy: "it's consistent with their materials". Beside K&R, I think the "Expert C" by "Peter von der Linden" is the best and only necessary book for C programming.
 
If you think that's bad, you'd love the book Modern C (there's a link to a 20-chapter free PDF version). While technically correct, the conventions it uses still look strange to me:
Code:
int main(int argc, char* argv[argc+1])

char* strcpy(char dst[restrict static 1], char const src[restrict static 1])
If a function parameter is declared with the form T v[static 1], pass (void*)0 as that parameter in a call to that function and observe how Clang's -Wnonnull flag works for just that one case and not 0, 0UL, (int*)0, etc. I'm not saying it's a useless flag, but considering it only catches one specific case…

The standard NULL macro (with no single standard value) is discouraged as well. Apparently, some systems exist where NULL is defined to be a zero-valued integer literal of type T (e.g. 0, 0UL) and sizeof(T) < sizeof(void*), which can result in program crashes when passing NULL to variadic functions that expect pointers like printf(3) with certain format specifications and execl(3).

I also get the feeling that the author would have preferred this declaration of fgets(3) instead:
Code:
char* fgets(size_t n, char buf[restrict n], FILE* restrict stream);

C's syntax is confusing to a lot of people, and I'm honestly not sure if the conventions in the book make it better or worse.

I'm wary of using [static] etc nowadays. Let's face it compilers are pretty damn good at optimising. I mean, years ago we used to use register for every variable in a loop, nowadays, the compiler will ignore it and do what it wants (and do it better in most instances)

There may be times when you want to specify this stuff, in embedded or real time, for example, but for the average coding Joe, they're a nuance best left in the standard's boffins minds. (tautology)
 
Back
Top