Live data from Hacker News

Why undefined behavior may call a never-called function

kristerw.blogspot.com

121–130 of 183 posts

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

#121
post #117

Earlier quoted context omitted.

> The function called at program startup is named main, Incorrect. On Linux usually _start is called first and this can be freely changed at link time. LPT: Knowing a bit of JavaScript or whatever doesn't make you a systems engineer; don't act like it.

Right, yes, sure, whatever. Since you've evidently got the experience that I apparently lack, you'll know that this point is irrelevant, since the topic at hand is Standard C, and not whatever some random implementation happens to do... so I'm not sure what your point is. But of course perhaps it would be obvious to a more experienced practitioner. C standard reference: https://port70.net/~nsz/c/c11/n1570.html#5.1.2.…

Nothing in the C standard prohibits parts of the executable from (a) being outside the "program" and thus many of the limitations of the standard, and (b) running before main. Therefore on Linux and Windows and almost certainly OS X too, main is not called first. Anyone who knows anything about systems programming knows this or should. (See also: the 90 million My First Disassembly blog posts out there.)

But you know what else the c standard says? UB is UB. People in here complaining that UB is really unfair because it forces them to write correct programs are the ones bringing the real world into scope in this discussion. If you want to insist that we limit the discussion to the standard then you're just objectively wrong by definition, end of discussion. I was trying to be more productive than that.

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

#122
post #66

If the compiler can take advantage of undefined behavior to optimize a program, what is keeping the compiler from also warning you that it is doing so?

Because the useful types of optimisation around undefined behaviour aren't: "we can prove that your program definitely contains undefined behaviour, so we'll compile it into 'rm -rf /', mwahahaha" but rather: "if property P about your program is false, then it would definitely contain undefined behaviour, therefore P must be true" followed by using P to do useful optimisations.

This applies even when your original program contains zero undefined behaviour. Warning here isn't useful.

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

#123

Earlier quoted context omitted.

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.

I need Emacs to be secure. It's written in C. It interfaces with the internet.

Ditto for Bitcoin. It's the basis of a new financial system. The core software is written in C++.

Same for Linux. C.

Prejudice generally isn't helpful, and it's a bit strange that you can recognize C's merits while also decrying it.

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

#124

Earlier quoted context omitted.

Look at how often folks on HN complain that the Web platform is useless because JS is slow. I haven't actually seen anyone complaining about that. Do you have any links? There are some specific complaints like: JS can't do 64-bit arithmetic or SIMD; but that's only really needed for games and scientific computing, which don't need to use JS. Or that JS is single-threaded; that's a fundamental feature of its design, n…

> Nobody's talking about taking away all optimisations, just not trying to do extreme optimisations that exploit undefined behavior (or rather, assume it can never occur). Those "extreme" optimizations are usually just surprising behavior that emerges from perfectly reasonable optimizations. For example, assuming that code that follows null dereference is dead is important. > Plenty of C compilers worked that way in…

If I could get that on -O1 or -O2, or maybe -Os, I would very happily do so. (But I don't actually know what optimisations those entail without poring over the manuals.)

You're implying that 90s compilers had no optimisations, which is incorrect.

Why is this a hot topic now, and why was it not a hot topic 10 or 15 years ago?

I suggest that something changed in the interim, and that what changed is the addition of dangerous optimisations. I'm not sure where it all started but strict aliasing in GCC is a potential candidate.

As others have pointed out, GCC and Clang seem to have by far the most horror stories, even though they don't actually generate the fastest code. I imagine that's mostly because GCC and Clang are so widely used, though.

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

#125
post #49

Earlier quoted context omitted.

You're the last person I'd have expected to make that sound like a bad thing. While benchmark games played a part in the modern ‘undefined behavior’, I'm not so sure that it would made much difference to adoption of the language. Consider Linus Torvald's well-known rant as a point in the opposite direction. In the universe where ‘undefined behaviour’ had been clearly specified as ‘what you write is what you get’, C m…

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…

I don't see how it's an optimization to assume, at compile time, that a static pointer that is always null is actualy aiming at the function NeverCalled. Why not pick some other function, like one which prints a diagnostic and calls abort?

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

#126
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?

btw, this would work with slightly older rm from GNU coreutils:

  rm -rf --n /
any GNU long option (getopt_long) for any command can be shortened as much as there isn't any ambiguity. And hence the above (this is fixed in latest GNU coreutils release).

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

#127
post #2

Interesting choice of code for a demo. I wonder if anyone hosed themselves running this. It seems gnu rm has "-preserve-root" as a default, but that's not guaranteed to be on every rm.

but that's not guaranteed to be on every rm.

Not even the GNU Coreutils one, if compiled with this compiler.

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

#128
post #66

If the compiler can take advantage of undefined behavior to optimize a program, what is keeping the compiler from also warning you that it is doing so?

Because, after inlining and macro expansion and other passes, you'd get warnings about everything under the sun and they would be useless.

"I'm statically assuming that a pointer that can never be anything other than null actually refers to NeverCalled" is definitely worth a diagnostic.

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

#129

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…

I don't see how it's an optimization to assume, at compile time, that a static pointer that is always null is actualy aiming at the function NeverCalled . Why not pick some other function, like one which prints a diagnostic and calls abort ?

It's not aiming at the function NeverCalled; it's aiming at EraseAll.

As the article states, if a local static function has exactly one assignment to it, then it can be an important optimization to assume that it will always have that value. Imagine that it's some kind of "DebugPrintf(...)" function that, in release builds, is always set to a no-op that does nothing before being called. You would definitely want that indirect function call to be inlined to nothing in release.

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

#130

Earlier quoted context omitted.

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

I need Emacs to be secure. It's written in C. It interfaces with the internet. Ditto for Bitcoin. It's the basis of a new financial system. The core software is written in C++. Same for Linux. C. Prejudice generally isn't helpful, and it's a bit strange that you can recognize C's merits while also decrying it.

I haven't been "recognizing C's merits" either. In fact, the real reason behind this problem is that C is not type safe, so optimizations (such as the one in this very article!) that are perfectly fine to do in type-safe languages are not possible to do in C without aggressively "exploiting" undefined behavior.
Post reply on HN