Live data from Hacker News

Why undefined behavior may call a never-called function

kristerw.blogspot.com

81–90 of 183 posts

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

#81
post #40

Earlier quoted context omitted.

> It's really nice to be able to use abstractions that cost nothing because the compiler is smart. But the compiler is not smart. It's screwing up in certain cases. In this example if it was smart it would have figured out that the value never was initialized. > In this particular case, you might have a function pointer that exists for future expansion, but which currently only ever holds one value. Then define it as…

> if it was smart it would have figured out that the value never was initialized. But that's false, which just goes to show that the compiler writers know way more about this than you do. There's nothing stopping this from being linked into a binary which doesn't even call main, or which calls NeverCalled, etc. And I bet you will also insist stamping your feet that of course programmers should be able to construct fu…

>> if it was smart it would have figured out that the value never was initialized

> But that's false

Are you reading the same code the rest of us are? NeverCalled is never called. So Do is not explicitly initialized and therefore contains a null pointer because it's a static variable.

Now compiler writers wanted their benchmark scores better so instead of crashing the program when Do is called, which happens in the unoptimized version, they decided to play fast and loose with UB. They just made code vanish.

What I'm saying is that if the compiler can figure out that NeverCalled is actually called from somewhere then it's free to make these optimizations. But if it knows it's not called then it should either disable the optimization for that statement or better yet give a warning.

> There's nothing stopping this from being linked into a binary which doesn't even call main, or which calls NeverCalled, etc.

Which is why I called for Whole Program Optimization to solve that issue. Since it looks like you did not bother to find out what that is and how it would solve that issue I'll explain it here. In Whole Program Optimization the compile is pushed down to the link phase. This lets the compiler see the who program and apply optimizations globally instead of at a file by file bases. So it can tell if main is never called or if NeverCalled is called or not.

> And I bet you will also insist stamping your feet

Now you're attacking me instead of my arguments. Do you wish to have a civilized discussion or just resort to insults? Because if it's the latter I will just ignore you in the future.

> which just goes to show that the compiler writers know way more about this than you do

> You know nothing, but you're convinced you know so much more than those stupid compiler writers.

I am a compiler writer so I do know what I'm talking about. It's a small personal project but it means I've been doing a lot of thinking and research about compilers. And eliminating UB is my current design focus.

And if you reread what I wrote you can see I never called them stupid. They are quite smart and know what they are doing. But even a smart person can make bad decisions depending on their motivations. What I'm saying is that they are putting their skill towards exploiting UB instead of protecting programmers from it.

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

#82
post #67
post #57

rm -rf / Using this type of code to show unintended consequences is itself a hotbed of unintended consequences! Just put in code that prints "pwned" instead of running code that would delete someone's system or home folder.

Do any up-to-date operating systems actually run this without the --no-preserve-root flag?

The busybox rm does.

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

#83
post #31

Earlier quoted context omitted.

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.…

> Exactly how that happens can be left unspecified, but that it must happen cannot be unspecified in a sane design. I don't see how any reasonable person could possibly dispute this. Your proposal is basically tantamount to saying that the compiler can never ever delete any read or write to memory that is unused if it can't prove that the memory pointer is non-null (for example, the pointer is an argument to the func…

> Your proposal is basically tantamount to saying that the compiler can never ever delete any read or write to memory that is unused if it can't prove that the memory pointer is non-null

That's right. I would much prefer to take a small performance hit if I might be dereferencing a null pointer than to literally have anything at all happen in that case. If I really need that last little bit of performance I really do want my compiler to insist that my code be correct before it will give it to me rather than take a wild guess at what I really meant to do and get it wrong.

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

#84
post #83

Earlier quoted context omitted.

> Exactly how that happens can be left unspecified, but that it must happen cannot be unspecified in a sane design. I don't see how any reasonable person could possibly dispute this. Your proposal is basically tantamount to saying that the compiler can never ever delete any read or write to memory that is unused if it can't prove that the memory pointer is non-null (for example, the pointer is an argument to the func…

> Your proposal is basically tantamount to saying that the compiler can never ever delete any read or write to memory that is unused if it can't prove that the memory pointer is non-null That's right. I would much prefer to take a small performance hit if I might be dereferencing a null pointer than to literally have anything at all happen in that case. If I really need that last little bit of performance I really do…

How big a performance hit? Double run time? Triple? 10x?

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

#85
post #11

I have become convinced that the current screw-the-programmer interpretation of ‘undefined behaviour’ was not intended, or even imagined, by the original ANSI C committee. Within the committee's mandate to ‘standardize existing practice’, it was simply an acknowledgement that C compilers translated straightforward C code into straightforward machine code without adding safety checks, and that simple code might —​ in…

> the current screw-the-programmer interpretation of ‘undefined behaviour’ I don't believe that interpretation was ever followed by anyone. In C parlance, "undefined behavior" only means that the standard does not define any specific behavior for a particular case. In other words, that particular code construct isn't valid C, but the standard doesn't mandate it should be illegal because some C implementation somewher…

Your argument is tautologous. Any "clueless programmer" can "screw themselves due to ignorance" in any programming language. The question is how difficult it is for programmers to avoid mistakes and how aggressive the programming language is in punishing programmers for their mistakes. C is terrible by these measures.

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

#86
post #71

Earlier quoted context omitted.

How do you know it's never called? You can call the function from another file. It's not possible to know that the function is never called until link time.

No, the function pointer is declared static. It cannot be referred to outside the current file.

The function pointer is static. But the function that mutates it, NeverCalled, is not. One can still indirectly change that function pointer.

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

#87

Earlier quoted context omitted.

It's not just benchmark games. It's people's real-world code. Look at how often folks on HN complain that the Web platform is useless because JS is slow. C without optimizations is just as slow if not slower. Compiler optimizations are so good that people don't realize how much they rely on them. Linus was wrong when he complained about the compiler treating null dereference as undefined behavior. This is a very impo…

This is an important point, and it's why the "C should die" crowd is hard to take seriously. They've even started labeling people who use C as somehow morally suspect, as if we're bad people for choosing to use an unsafe language. We're knowingly putting people in danger! Right. It's strange that the word "unsafe" has tainted people's thoughts so dramatically. Like calling torrenting music "piracy."

If one don't follow the High Integrety, CERT, MISRA standards, validated with tools like LDRA.

Or at very minimumm compiling with warning enabled as errors, with a continuous build breaking on static analysers errors, then yes.

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

#88

Earlier quoted context omitted.

It's not just benchmark games. It's people's real-world code. Look at how often folks on HN complain that the Web platform is useless because JS is slow. C without optimizations is just as slow if not slower. Compiler optimizations are so good that people don't realize how much they rely on them. Linus was wrong when he complained about the compiler treating null dereference as undefined behavior. This is a very impo…

This is an important point, and it's why the "C should die" crowd is hard to take seriously. They've even started labeling people who use C as somehow morally suspect, as if we're bad people for choosing to use an unsafe language. We're knowingly putting people in danger! Right. It's strange that the word "unsafe" has tainted people's thoughts so dramatically. Like calling torrenting music "piracy."

I'm not endorsing C. Don't use C for anything you need to be secure.

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

#89
post #65

Earlier quoted context omitted.

It's not just benchmark games. It's people's real-world code. Look at how often folks on HN complain that the Web platform is useless because JS is slow. C without optimizations is just as slow if not slower. Compiler optimizations are so good that people don't realize how much they rely on them. Linus was wrong when he complained about the compiler treating null dereference as undefined behavior. This is a very impo…

But sometimes these checks just seem to end up entirely removed, and that is just not OK: I have been a developer working on performance constrained system software in low-level programming languages (including heavily optimized games written in C++) and this undefined behavior idea has gone way way too far. I can always make code faster by removing checks I don't need manually: trying to compare the small gains here…

These optimization opportunities aren't small gains. They have big consequences, for example when they cause code that would not be vectorized to be vectorized. Again, compiler authors don't add UB optimization for the fun of it. Patches to add theoretical optimizations that don't actually move the needle are routinely rejected from LLVM and GCC (as they should, because optimizations slow down compilation, so they need to pull their weight). Rather, they add UB optimization when code is shown to benefit, often the code that people come to their bug trackers with complaining that it doesn't optimize to what they expect.

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

#90

I suspect this is another critical point: as NeverCalled may have been called from, for example, a global constructor in another file before main is run clang doesn't analyse across module boundaries --- even when it theoretically could --- so it doesn't know for certain that NeverCalled() is indeed never called. Throughout the years I've grown increasingly displeased at how compilers handle even trivial cases like t…

  more sensical approach to analysing this program, e.g. as employed by a human, would be to see that NeverCalled() is the only function that can write Do
It is not only non-trivial but also impossible (even) for a human to see if NeverCalled is ever called. Since NeverCalled is visible to other translation units, it can be called, for instance, by a global constructor before main is called.

Adapting thinkings such as

  "I can't figure out how to optimise this, so I'll do the simplest thing that works."
will disable the compiler from many non-trivial optimizations. Consider eliminating a branch predicated on `w expected by the programmer to be eliminated, a result of constant-progagation, or a result of other optimizations.

Saying you have ideas but don't have time to make a better compiler only makes you an armchair compiler-writer.

Post reply on HN