4 ms·
The biggest problem with UB, as interpreted by C/C++ compilers is the unfounded belief that the spec says that you can assume any path that leads to UB is defac
by olliej 4y ago
The biggest problem with UB, as interpreted by C/C++ compilers is the unfounded belief that the spec says that you can assume any path that leads to UB is defacto incorrect and can be ignored. That's the bogus logic required for steps 13-16 to be true.
That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work without falling afoul of their invented nonsense.
- maccard 4y agoThis is an absurd reduction of the current situation. > That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work without falling afoul of their invented nonsense. I've never heard of anything like this, have you any sources for this happening?
- rightbyte 4y agoRead the gcc mailing list. There is alot of user hostile "fix your broken program" from language lawyers. I think aliasing rules messes up memcpy if you are dogmatic?
- ilyt 4y agoTo be fair it is extremely easy to write broken C/C++ program
- maccard 4y agoTheres a big difference between "the GCC mailing list is full of language lawyers" and "memcpy doesn't work because UB and the compiler Devs fixed it by adding an exception for it". > I think aliasing rules messes up memcpy if you are dogmatic? I'm _not_ dogmatic or a language lawyer and aliasing is a total pain in the ass, but that's a whole different topic to compilers getting fundamentals wrong because of language lawyering.
- anonymoushn 4y agoI think memcpy is fine because it operates on a special type that is allowed to alias anything. Strict aliasing has other fun issues like the impossibility of implementing malloc-like functions or the lack of any requirement for access to non-char members of structs to work at all[0]. [0]: https://stackoverflow.com/questions/49298704/how-reason-about-strict-aliasing-for-malloc-like-functions#comment87025368_49988951 https://stackoverflow.com/questions/49298704/how-reason-abou...
- olliej 4y agomemcpy is UB because it reads padding bytes in structs. memmove fails as it requires pointer comparisons between separate allocations, which is UB.
- anonymoushn 4y agoSounds like we shouldn't use memcpy on structs containing padding!
- maccard 4y agoNo, memcpy is fine because it's a language level function. What you _can't_ do is implement your own memcpy alternative safely.
- nayuki 4y agomemcpy() and memmove() are language-level functions. They are allowed to do things that cannot be implemented in user code. The C standard library's implementation of these functions have tight integration with the compiler to ensure that it can implement all the required semantics without triggering undefined behavior.
- leni536 4y agoreading padding bytes is not UB. Comparing unrelated pointers is unspecified, not undefined. It's also an implementation detail of memmove. It can use a magical total order comparison of pointers that is otherwise unavailable to users of the language.
- olliej 4y agomemset, memcpy, and memmove, etc all depend on UB. memset and memcpy read and write padding bytes, which is UB. If you try to say memset/cpy is a "primitive operation", then you're still stuck with the "correct" struct initialization (memset, bzero) being UB if you did something like: void f(bool condition) { if (condition) { struct structwithpadding thing; bzero(&thing, sizeof(thing)); } else { printf("wat\n"); } } The ludicrously broad definition of what UB apparent allows, this can be "optimized" to void f(bool condition) { printf("wat\n"); } Because bzero() writes to padding, and that is UB, which means the condition==true branch "can't happen" \o/ memmove falls to UB much requires pointer comparisons between pointers to different objects, which is UB.
- ilyt 4y agoWouldn't really be a problem if the design of those languages wasn't horribly ridden with footguns. Compiler designers just chose the notion of "obviously user wouldn't invoke the footgun, so any code that would be causes by footgun can be removed"
- MushyQuadrant 4y agoThis is a necessary consequence (in the formal logic sense) of the "principle of explosion"[1] for optimizing compilers. If the compiler assumes some undefined behavior does not occur, but in fact that undefined behavior does occur, all of conclusions it makes which depend, directly or indirectly, on the contradicted assumption are invalid. Since, in the process of optimization, optimizing compilers make conclusions about parts of a program based on other parts of the program which may be executed later, undefined behavior in one part of a program causes invalid conclusions about other parts which may be executed earlier. Therefore undefined behavior cannot be contained to just parts of a program executed after a particular part, if the compiler tries to optimize parts of the program based on parts that may be executed later. [1]: https://en.wikipedia.org/wiki/Principle_of_explosion https://en.wikipedia.org/wiki/Principle_of_explosion