5 ms·
I am intrigued as to why the compiler feels it is allowed to simplify a function returning nothing as a no-op. After all this function allocates memory and stor
by Iv 8y ago
I am intrigued as to why the compiler feels it is allowed to simplify a function returning nothing as a no-op. After all this function allocates memory and stores things in there. This is a side effect that the optimization suppresses.
- marcoperaza 8y agoThe allocation’s address is only ever stored into a local variable. The compiler can therefore prove it’s not used elsewhere (short of e.g. scanning the whole heap for it)
- plorkyeran 8y agoThe compiler assumes that you have given it a valid C program, and optimizes accordingly. A valid C program is not allowed to fall off the end of a non-void function without returning a value if the return value is used. This means that if the optimizer sees a function which will always do this, it "knows" that you never call it (as if you did, your program would be invalid). Since the function is never called, there's no point in emitting any code for the body of the function. It still needs to emit a small stub, as you could legally take the address of it. As it so happens your program does call this function. This makes your program not a valid C program, and so the standard says nothing about how it should behave.
- deleted 8y ago[deleted]
- jchw 8y agoThe C attitude is simple. If your code invokes undefined behavior, the compiler is allowed to do whatever it wants. Not returning a value from a function that is not void is definitely a footgun. The C language itself does not prevent you from invoking these footguns. Why, I don't know for sure; I wasn't around for the genesis of C. I would guess that if C were designed today, most of the undefined behavior that can be detected statically would just be errors. Of course, compilers are allowed to optimize assuming your code does not utilize undefined behavior. This is reasonable in my opinion. If the compiler were not allowed to optimize in ways that broke undefined behavior, it would be nearly impossible to write meaningful compiler optimizations. Most compiler optimizations change the semantics of the execution even though they keep the semantics of the program itself identical according to the rules of the C language. Where would you draw the line? If I monkey patch a function that my compiler decided to inline, would I have reason to complain? In the face of C seeing your completely unused side-effects, it knows there is no possible way your program could ever actually touch those side-effects in the bounds of defined behavior. Therefore, it is free to throw them away. This may seem unreasonable, but in my opinion it's nearly the only reasonable choice. To me the real solution is something like -Wall -Werror. For most statically detectable invocations of undefined behavior, this will save you, throwing an error in this case because "not all codepaths return a value." Then, you can sleep easy without sacrificing decent dead-code elimination.
- Iv 8y agoThat actually made sense. I just wanted to point out that for me, C is more for embedded code, where modifying random parts of memory is a common task. So saying that a function that filled a pointer, used it to reset or set some parts of memory can be removed just because it does not have a return seems a bit extreme, but I agree that it is allowed. I often see people pushing for -Wall and -Werror. In most professional projects I have been in, though, we have to use black boxes (or, currently, non-standard compilers) that prevent correcting many warnings. I wish we had a finer granularity there but well...
- 0xTJ 8y agoC is a language where you're expected to know what you're doing. While it wasn't necessarily right in this case, it's assumed that the generated assembly should match the intent of what you gave it.