Live data from Hacker News

Why undefined behavior may call a never-called function

kristerw.blogspot.com

151–160 of 183 posts

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

#151

Earlier quoted context omitted.

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…

For debug functions that completely disappear in release builds, we have inline functions with conditionally empty bodies or old-school macros.

It is a (decades ago) Solved Problem.

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

#152
post #150
post #63

Earlier quoted context omitted.

$ uname -sr FreeBSD 11.1-RELEASE $ rm -rf / rm: "/" may not be removed No idea about other BSDs. Busybox's rm is indeed happy to nuke /.

Also: $ uname -sr OpenBSD 6.1 $ rm -rf / rm: "/" may not be removed

The latest POSIX standard actually requires this behavior:

If […] an operand resolves to the root directory, rm shall write a diagnostic message to standard error and do nothing more with such operands.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/rm...

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

#153
post #81

Earlier quoted context omitted.

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

Just wanted to say, I think your comments here are useful. Given some of the replies, I guess the person who said that this is "literally a religious issue" is right. Sigh!

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

#154

Earlier quoted context omitted.

If there were a simple and reliable way to say "make the program crash if we hit any of this UB, rather than optimising it completely away" I think that would make a lot of people happy.

LLVM already does this as much as possible. Look at how Clang inserts "ud2" instructions in dead code paths.

Is there a way to use that to address the "NeverCalled" example?

I feel like there's a huge disconnect here. Even after the strange behavior is explained, some people say "wow, I never ever want that behavior, how do I reliably avoid it?" but others respond "there's no problem, you're just using it wrong".

Is there really no way to satisfy both sides?

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

#155
post #136

Earlier quoted context omitted.

What language do you think would have replaced it? It seems to me that C had already won as the de facto systems language, long before any of these "modern optimisation techniques" cropped up. Optimisations that make it harder to use the language safely are downright dangerous in my book.

I would have been happy with Modula-2, Ada or Object Pascal as basis. But better yet would have been Modula-3 or Active Oberon.

I hear very good things about Ada, aside from its unfriendly old-fashioned syntax.

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

#156
post #136

Earlier quoted context omitted.

I would have been happy with Modula-2, Ada or Object Pascal as basis. But better yet would have been Modula-3 or Active Oberon.

I hear very good things about Ada, aside from its unfriendly old-fashioned syntax.

Some of us do enjoy verbose explicit syntax instead of hieroglyphs. :)

Quite helpful when maintaining unknown code in big corp projects.

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

#157

Earlier quoted context omitted.

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.

The compiler doesn't know the pointer isn't set, only the linker may know that. So you'd have to put a whole lot more smarts into multiple tools to get that warning.

I'm not convinced it is useful.

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

#158

Earlier quoted context omitted.

> It also knows that it can't be NULL at the call site Ah, this is obviously some strange use of the word "can't" that I wasn't previously aware of. Or possibly of "be" or "at". The pointer clearly is NULL at the call site. Observe: http://lpaste.net/358687 . Hypotheticals about the program being linked against some library that that calls NeverCalled are just that, hypothetical. In the actual program that is actuall…

"Can't" here means that your program is not well-formed otherwise, and the compiler assumes well-formedness. I assume you don't like that, but I wonder if you'd apply that to other optimizations? For a random example: int x = 42; SomeFunc(); printf("%d\n", x); Should the compiler be allowed to hard-code 42 as the second parameter to printf, or should it always store 42 to the stack before calling SomeFunc(), then loa…

Hardcoding 42 as the parameter to printf here is far more defensible for several reasons. Here's one: the value actually is 42, and assuming that it continues to be 42 doesn't require the compiler to hallucinate any additional instructions outside this compilation unit.

There's a difference between assuming that a function like SomeFunc internally obeys the language semantics for the sake of code around its call site (this is the definition of modularity), and assuming that because the code around the call site "must" be "well-formed" this allows you to hallucinate whatever code you need to add elsewhere to retroactively make the call site "well-formed" (this is the definition of non-modularity).

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

#159

Earlier quoted context omitted.

"Can't" here means that your program is not well-formed otherwise, and the compiler assumes well-formedness. I assume you don't like that, but I wonder if you'd apply that to other optimizations? For a random example: int x = 42; SomeFunc(); printf("%d\n", x); Should the compiler be allowed to hard-code 42 as the second parameter to printf, or should it always store 42 to the stack before calling SomeFunc(), then loa…

Hardcoding 42 as the parameter to printf here is far more defensible for several reasons. Here's one: the value actually is 42, and assuming that it continues to be 42 doesn't require the compiler to hallucinate any additional instructions outside this compilation unit. There's a difference between assuming that a function like SomeFunc internally obeys the language semantics for the sake of code around its call site…

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.

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

#160
post #92

Earlier quoted context omitted.

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…

The craziness for C optmizer tricks is in many cases plain phsycologic. As an example, it doesn't matter that it does in 5ms what it takes to do in 15ms without the optimization, if in the end anything less than 20ms doesn't have visibile outcome. Actually there is a remark from a famous compiler write (female), which I don't recal the name now, that C brough back into the stone age what the optimizers were already a…

So now the compiler should also statically figure out how long some code is going to take to run?

Chances are I want the compiler that gives me a binary that does its job in 2 hours rather than 6.

Post reply on HN