4 ms·
You don't give up any portability. If the standard says that say, dereferencing a NULL pointer is UB it means you're not supposed to do that ever, on any OS or
by dale_glass 3y ago
You don't give up any portability.
If the standard says that say, dereferencing a NULL pointer is UB it means you're not supposed to do that ever, on any OS or compiler. A compiler can choose to do something sensible like producing a fatal error message without any downside, since per standard that's not ever supposed to happen anyway.
- weinzierl 3y agoTo not giving up portability all compilers would have to do what you propose. They won't as long as the standard doesn't mandate it. So we are back at the point where we agree that the standard contains some unfortunate things. Now, standard conformant compilers do exactly what you propose, they are just not C or C++ compilers and the standard is not the C or C++ standard.
- dale_glass 3y ago> To not giving up portability all compilers would have to do what you propose. Not in a lot of cases. Eg, let's suppose that GCC defines a NULL pointer dereference to act exactly like a normal one. That is, the compiler dereferences the pointer, and whatever the CPU/OS says is going to happen when you read from 0x0, happens. Meanwhile, Clang continues with behaviors that can say lead to a function being entirely replaced with "return true". There's no problem whatsoever with this. You're still not supposed to dereference null pointers. It's just that on GCC in particular you get a predictable error. And being an error you can't really rely on it -- your program still crashes and crashes are still undesirable, and therefore you will fix whatever leads to that outcome. And on Clang maybe you don't crash but the program doesn't do what you expect it to, which is still a bug to be fixed. You have a bug in both versions which manifests in different ways (but that is fine, because UB says anything goes so there's no requirement whatsoever for both compilers to have the program break identically), but it's the same bug that needs the same fix. After the bug fix, your GCC compiled version doesn't crash and runs correctly, and your Clang compiled version doesn't crash and runs correctly. The behavior in the end is identical.
- Kamq 3y ago> If the standard says that say, dereferencing a NULL pointer is UB it means you're not supposed to do that ever, on any OS or compiler. Says who? The standard doesn't say that. At most it says that if you're trying to write portable C, you shouldn't do that. But not everyone is trying to write something portable.
- dale_glass 3y agoThe standard does say it. UB means there are absolutely no rules regarding what happens. It's not implementation defined, it's "absolutely anything can happen and it can change unpredictably".
- Kamq 3y ago> UB means there are absolutely no rules regarding what happens. I will acknowledge that the standard says this, but the original post said "you're not supposed to do that ever". Those are not the same thing.
- dale_glass 3y agoThey are. First, because the compiler isn't bound to any promise. If in version 2.0, you can still use memory immediately after freeing it, version 2.0.1 is perfectly free to make the program misbehave. No consistency has been promised. Second, because per the linked article, compilers treat UB in a particular, weird way. Compilers assume you will not invoke it. Hence this example: #include <stdio.h> int main() { for(int i; i < 10; i++) { printf("%d\n", i); } return 0; } Which a real compiler compiles to this: #include <stdio.h> int main() { return 0; } Why? Because usage of an uninitialized variable is UB. UB is something a programmer doesn't intend to invoke. Therefore the compiler concludes "(undefined)i < 10" never happens. Therefore the loop never runs. Therefore the loop can be removed. UB is not just non-portable, modern compilers treat it as a weird, radioactive state they avoid touching.
- Kamq 3y ago