Live data from Hacker News

Why undefined behavior may call a never-called function

kristerw.blogspot.com

171–180 of 183 posts

Re: Why undefined behavior may call a never-called function

#171
post #19

Earlier quoted context omitted.

This, just so much this! I've been longing for a C compiler with a "sane optimizations only"-switch like forever. I'd gladly give up on the additional couple of per cent speed improvement obsessive compulsive compiler writers managed to eke out by ignoring the source codes' obvious intentions and defending it with "but technically it's undefined behaviour"!

Everyone posts a comment like this every time undefined behavior surprises someone. But the reality is that the reason why C remains alive is that compiler writers have managed to make it fast. It is not "a couple of percent": these kinds of optimizations can make an enormous difference when, for example, they're the difference between vectorizing a loop and not doing that. Compiler writers are not "obsessive compuls…

[deleted]

Re: Why undefined behavior may call a never-called function

#172

Earlier quoted context omitted.

> Your argument is tautologous. Any "clueless programmer" can "screw themselves due to ignorance" in any programming language. It appears you're missing the fact that someone needs to be completely oblivious and very foolish to expect anything out of behavior which was intentionally left undefined. I mean "undefined behavior" clearly signals that no particular behavior should be expected. A programmer needs to be par…

> A programmer needs to be particularly clueless and specially incompetent to write code that has unexpected consequences No. That's called "a bug".

> No. That's called "a bug".

You need to actively go against the most basic aspects of the programming language you're using to force undefined behavior into your code. So, it's not merely a bug. It's the direct result of incompetence, and one which no programmer can pin on his tools or even the programming language.

Re: Why undefined behavior may call a never-called function

#173

Earlier quoted context omitted.

What's the difference between assuming that a function you call will obey the language semantics, and assuming that the function that calls you will obey the language semantics? That's the only difference I can see.

> assuming that the function that calls you will obey the language semantics That's not what I said. What the compiler is doing in this NeverCalled example is observing: - that the code in the current compilation unit is not "well-formed", but - that the compilation unit can be "rescued" by some other module that could be linked in, if that other module did something specific, and therefore concluding that it should…

When you say "its stated interface," are you referring purely to the prototype, or are you referring to documented behaviors, or what? Because it seems reasonable to me for a function with no parameters to have prerequisites before you call it, and it seems unreasonable to say that it must be valid to call a function with no parameters in any and all circumstances.

Re: Why undefined behavior may call a never-called function

#174
post #31

Earlier quoted context omitted.

Unfortunately, "it's not a bug, it's a feature!" -- there are long-standing design choices in C/C++ where various circumstances are explicitly designed to yield "undefined" behavior where literally anything goes. I believe the original intent of these are to give the compiler/optimizer more room to speed up the executable. Edit: The 'undefined' clause here is due to invoking a function at address 0, rather than any l…

It is a bug, but it's a bug in the spec. Saying that a common mistake like dereferencing the null pointer is undefined and therefore your program can do anything is not useful behavior. The only sane design is for any attempt to dereference the null pointer to cause the program to signal an error somehow. Exactly how that happens can be left unspecified, but that it must happen cannot be unspecified in a sane design.…

Yeah, I completely agree that this behavior is not sane. It is designed behavior, perhaps designed so with good intentions, but foolish assumption nonetheless (that the “undefined” behaviors would be predictable if left truly undefined).

So yeah, I’m pretty happy to call this a “design bug” in the entire language. Those kinds of bugs are hard to fix, because you need the whole C++ committee to fix this, and we all know how bad design-by-committee performs.

So just switch to Rust :)

Re: Why undefined behavior may call a never-called function

#175
post #167

Earlier quoted context omitted.

The point of the warning is precisely that the compiler is making a dangerous assumption without proof. More smarts is needed only to eliminate false positives occurrences in the warning.

> the compiler is making a dangerous assumption without proof. The whole issue is that, from the compiler point of view, it has a proof! It can prove from the language rules that the pointer can only have NULL and EraseAll as its value; since a call through the NULL pointer is invalid, at that line the only value left is EraseAll; QED. It might not be the proof you wanted, since you disagree with the premises, but it…

It isn't a valid proof, because it's perfectly possible that the variable has a null value and that the call is invalid.

Detection of that null value is already there and essentially free of charge.

The implementation is going out of its way to prevent an instance of undefined behavior from being detected, without providing a useful, documented extension in its place, and in a situation when the detection costs nothing.

Re: Why undefined behavior may call a never-called function

#176

Earlier quoted context omitted.

> A programmer needs to be particularly clueless and specially incompetent to write code that has unexpected consequences No. That's called "a bug".

> No. That's called "a bug". You need to actively go against the most basic aspects of the programming language you're using to force undefined behavior into your code. So, it's not merely a bug. It's the direct result of incompetence, and one which no programmer can pin on his tools or even the programming language.

> You need to actively go against the most basic aspects of the programming language you're using to force undefined behavior into your code.

Adding two ints together is potentially undefined behaviour.

Re: Why undefined behavior may call a never-called function

#177
post #167

Earlier quoted context omitted.

> the compiler is making a dangerous assumption without proof. The whole issue is that, from the compiler point of view, it has a proof! It can prove from the language rules that the pointer can only have NULL and EraseAll as its value; since a call through the NULL pointer is invalid, at that line the only value left is EraseAll; QED. It might not be the proof you wanted, since you disagree with the premises, but it…

It isn't a valid proof, because it's perfectly possible that the variable has a null value and that the call is invalid. Detection of that null value is already there and essentially free of charge. The implementation is going out of its way to prevent an instance of undefined behavior from being detected, without providing a useful, documented extension in its place, and in a situation when the detection costs nothi…

If the variable has a null value and the call is invalid then the compiler isn't required to compile it to anything specific; this includes the idea that the compiler isn't required to compile it to a jump-to-address-zero.

Re: Why undefined behavior may call a never-called function

#178

Earlier quoted context omitted.

It depends on your definition of dangerous. And eliminating false positives in warnings is hugely important. Too many important warnings (more important than this one) are ignored today because people get desensitized as a result of so many false positives. Let's not add more for trivial issues like this please.

Warnings are ignored because people don't use -Werror and then fine tune which warnings warnings they want and don't want to see.

Warnings are ignored because it's too hard or not possible to configure the compiler to only issue the warnings a particular developer finds useful and actionable.

Adding more warnings, especially for silly corner cases like the example we're discussing, is not the solution.

Re: Why undefined behavior may call a never-called function

#179

Earlier quoted context omitted.

It isn't a valid proof, because it's perfectly possible that the variable has a null value and that the call is invalid. Detection of that null value is already there and essentially free of charge. The implementation is going out of its way to prevent an instance of undefined behavior from being detected, without providing a useful, documented extension in its place, and in a situation when the detection costs nothi…

If the variable has a null value and the call is invalid then the compiler isn't required to compile it to anything specific; this includes the idea that the compiler isn't required to compile it to a jump-to-address-zero.

> the compiler isn't required to compile it to anything specific

That might be true if the ISO C standard were the only source of requirements going into the making of that compiler; it isn't.

There are other issues.

Obviously, the compiler is in fact compiling it to something very specific. It's not simply an accident due to the situation being ignored that the indirect call gets replaced by a direct jump. The translation is deliberate.

From ISO C: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

This is definitely not the result of "ignoring the situation completely"; ignoring the situation completely means translating the code earnestly and subsequently the translation doing the indirect jump attempt through a null pointer. That's what it means not to do anything specific. It's not terminating the translation, so it's not the third kind of behavior. So it must be "behaving during translation or programing execution in a documented manner characteristic of the environment". I don't see how this is a characteristic of the environment; nobody can claim with a straight face that this is environmentally dictated!

Also, the undefined behavior never actually occurs. A pointer variable may be null; null is a valid value. Undefined behavior only ensues when the attempt is made to dereference. That's not actually happening in the program; the translation is devoid of any attempt to dereference null. The idea that the null pointer dereference caused the translation and the subsequent call to that function requires a perverted view of causality in which later events cause earlier events.

Re: Why undefined behavior may call a never-called function

#180

Earlier quoted context omitted.

Warnings are ignored because people don't use -Werror and then fine tune which warnings warnings they want and don't want to see.

Warnings are ignored because it's too hard or not possible to configure the compiler to only issue the warnings a particular developer finds useful and actionable. Adding more warnings, especially for silly corner cases like the example we're discussing, is not the solution.

> Warnings are ignored because it's too hard or not possible to configure the compiler to only issue the warnings a particular developer finds useful and actionable.

That's why you don't do that based on the whims of an individual developer. Simply have a "no warnings" policy. Then the project decides what is enabled and what isn't.

A commit must not introduce warnings.

If a code change triggers a warning, it must be accompanied with a disabling of that diagnostic, which must then pass review so that it is peer approved.

If the warning cannot be disabled, the change must be reworked.

This "silly corner case" is not silly at all; it reveals a dangerous translation strategy in the compiler. The appropriate treatment isn't the issuance of a warning; rather, this translation strategy should be turned off unless explicitly requested by an exotic code generation option. (And then it can be applied without any warning.)

Post reply on HN