Live data from Hacker News

Why undefined behavior may call a never-called function

kristerw.blogspot.com

111–120 of 183 posts

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

#111
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 original ANSI C committee had no idea about modern optimization pipelines. If people had continually pushed back against undefined behavior back then, there's a good chance that by 2017 the result would have been that C would be dead , replaced by a language that allows for modern optimization techniques.

As others have said, if C were dead by now that would be great.

But I'm pretty skeptical, to be honest. I've been working on one or another high-performance C or C++ program for most of the past 20 years. I can't ever remember getting a really substantial speed improvement from upgrading the compiler for an important platform, because anything the old compiler did badly that really hurt program performance had already been avoided, either before or after seeing it in profiling results. I'm sure that if you took C code developed on a modern compiler and compiled it with a 90s compiler, it would be slower. But I doubt the software ecosystem would actually be drastically slower if optimizer technology hadn't advanced significantly since 1995, and everything had been developed under that constraint. And I don't think every single advance in optimization since 1995 is dependent on degenerate transformations of undefined behavior.

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

#112
post #99

Earlier quoted context omitted.

Then there is an easy solution: compile with -O0. What's the problem with optimizations being available for those who want them?

There is absolutely no problem with optimizations being available. The problem is that the standard gives the compiler license to muck with the semantics of the program in highly non-intuitive and potentially dangerous ways, and this is true regardless of what flags are passed to the compiler. So I can't depend on anything working even if I specify -O0, at least not by the standard. I am entirely at the mercy of the…

> So I can't depend on anything working even if I specify -O0, at least not by the standard. I am entirely at the mercy of the benevolence of my compiler vendor.

What you're basically saying is that you want semantics that's basically defined by the compiler vendor (or, more accurately, compiler/operating system/hardware trio), but you're pissed that the standard leaves it up to the compiler vendor as to whether or not you will get that option. You're already "at the mercy of the benevolence of [your] compiler vendor" to give you things like uint32_t, why is the presence of a -O0 inherently worse?

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

#113
post #80

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…

The function called at program startup is named main, which this translation unit defines. No other may therefore define it. Binaries that don't run main are out of the scope of the standard, and so irrelevant to the discussion. Anyway, as a more general point: your argument is, basically, "the customer is wrong". But the customer is never wrong! Therefore your argument is invalid.

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

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

#114
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…

Go back to JavaScript, dear. You'll learn about real systems languages when you're older.

Seriously. This just isn't how computers work. Main doesn't just get magically called in a vacuum.

I don't see how a play project writing a compiler which is going to solve all those problems other compiler writers couldn't solve, while you don't even have a basic grasp of systems programming, helps your argument that you aren't being incredibly arrogant and naive in the face of more knowledgeable predecessors.

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

#115

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.

[deleted]

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

#116
post #30

Earlier quoted context omitted.

Exactly. This isn't "fuck the programmer if he fucks up," it's "let's try to do really good optimizations." It's really nice to be able to use abstractions that cost nothing because the compiler is smart. In this particular case, you might have a function pointer that exists for future expansion, but which currently only ever holds one value. In a case like that, it's really nice if the compiler can remove the indire…

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

> In what sense is the function pointer "not NULL"

If the pointer is NULL, dereferencing it destroys the universe. If the universe is destroyed, the program never existed. Therefore, in any universe where the program exists, the pointer is not NULL. Q.E.D.

Exercise 1: Propose a less parochial definition of universe that doesn't lead to colorful threats from major stakeholders.

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

#117
post #80

Earlier quoted context omitted.

The function called at program startup is named main, which this translation unit defines. No other may therefore define it. Binaries that don't run main are out of the scope of the standard, and so irrelevant to the discussion. Anyway, as a more general point: your argument is, basically, "the customer is wrong". But the customer is never wrong! Therefore your argument is invalid.

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

(A freestanding environment may start anywhere - but such environments are unusual.)

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

#118
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…

[deleted]

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

#119
The problem here is that the behavior is in fact defined. It is not defined by ISO C, so it is "(ISO C) undefined behavior". But requirements for C program behavior do not only come from ISO C. It takes more requirements than just those from ISO C to make a complete implementation.

On "modern", Unix-like, virtual memory platforms, we have an understanding that the null pointer corresponds to an unmapped page, and that this is the mechanism for trapping null pointer dereferences (at least ones that don't index out of that page).

A compiler which interferes with this by replacing valid null pointers with garbage at point where they are dereferenced is running afoul of this platform requirement.

Look, the generated code is not even pretending to use the value of the null variable. We cannot reasonably call this machine code a translation of the program's intent into machine code.

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

#120

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…

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 the 90s and performance was perfectly acceptable (on hardware with a fraction of the speed and memory of today's computers and phones).

You can get that experience with GCC -O0. Do you want to run code like that? I don't, and neither do customers.

People who don't work on modern compilers often think that there is a subset of "simple" optimizations that catches "obvious" things, and optimizations beyond that are weird esoteric things nobody cares about. That isn't how it works. Tons of "obvious" optimizations require assumptions about undefined behavior.

Post reply on HN