Live data from Hacker News

“gcc will quietly break nearly half of all the packages that it compiles”

metzdowd.com

21–30 of 110 posts

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#21
post #11

Earlier quoted context omitted.

Just read the email.

Actually it's still a useful question, I think. A simple example is function argument evaluation order. If you have: foo(bar(), baz()) A compiler is free to call these functions in either order. That means if baz relies on state mutated by bar, the program may behave differently if the compiler chooses to reorder evaluation.

There's a parable where a man goes to the doctor and says, "Doctor, whenever I drink my coffee with the spoon in the cup, the spoon handle pokes me in the eye and it hurts." And the doctor says, "Well, stop doing that."

If you wrote `foo(bar(), baz())` and `baz()` relies on state mutated by `bar()`, your code is bad, and you should feel bad, because experiencing those bad feelings is the way you learn to not write bad code. This code was wrong before the compiler reordered the calls, it just failed silently for a while. The compiler isn't responsible for fixing your bugs, you are.

People need to stop expecting other people to fix their problems.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#22
post #11

Earlier quoted context omitted.

Just read the email.

Actually it's still a useful question, I think. A simple example is function argument evaluation order. If you have: foo(bar(), baz()) A compiler is free to call these functions in either order. That means if baz relies on state mutated by bar, the program may behave differently if the compiler chooses to reorder evaluation.

That is called unspecified behavior not undefined behavior. Major difference.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#23

The only reasonable thing to say about this was already said upthread of the page, and quoted here: > I have worked on many programs, and whenever I found such a problem (typically called a "portability problem"), where the code was assuming something that the language did not guarantee, I fixed the program rather than bitching about the compiler.

IMO, it's a little subtler than that. It's not the compiler's fault, it's the language's. Plenty of languages have no undefined behavior that can be written by accident. Go and safe Rust, for instance, have just about no undefined behavior at all, and are both performance-competitive with C. (Go has UB if you cause race conditions, and Rust has UB within `unsafe` blocks analogous to C's UB.)

A C compiler, meanwhile, has to aggressively take advantage of undefined behavior to get good performance, and the C specification has been keeping behavior undefined for the benefit of compilers.

You can hope that you find all such problems in C (which you might not) and "fix the program", but you can also "fix the program" by switching to a better language.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#24

Inknow people are quick to complain about programmers relying on UB here but this really is a long standing disagreement with the gcc folk. They are language lawyers of the worst sort and do not consider security implications being a point of discussion :(

[deleted]

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#26

Earlier quoted context omitted.

A perhaps more interesting, quite realistic example: lock_two_widgets(widget *a, widget *b) { if (a lock); lock(&b->lock); } else { lock(&b->lock); lock(&a->lock); } }

If lock calls include a memory barrier, which they should, then they cannot be reordered. Edit: Your code has undefined behavior, unless the two pointers point to the same object, which is unlikely in a realistic example.

Yes, the pointer comparison is UB but if the compiler didn't go out of its way to screw you over UB code then it would be a reasonable way to prevent deadlock.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#27
post #26

Earlier quoted context omitted.

If lock calls include a memory barrier, which they should, then they cannot be reordered. Edit: Your code has undefined behavior, unless the two pointers point to the same object, which is unlikely in a realistic example.

Yes, the pointer comparison is UB but if the compiler didn't go out of its way to screw you over UB code then it would be a reasonable way to prevent deadlock.

There is a defined method for comparing such pointers. Take unsigned char pointers to them and inspect their bytes. Then write your code, using that information, that does the comparison, assuming you know your architecture.

It is defined behavior to read the bytes of any object using unsigned char.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#28

Inknow people are quick to complain about programmers relying on UB here but this really is a long standing disagreement with the gcc folk. They are language lawyers of the worst sort and do not consider security implications being a point of discussion :(

> On two occasions I have been asked, — "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. --Charles Babbage

The modern version of this seems to be:

"Mr. Babbage, I put the wrong figures into the machine and the wrong answers came out! Please fix it this, this has security implications!"

You can't reasonably expect the compiler to make your insecure code secure.

Calling them "language lawyers" is some entitled crap. GCC commits to implement the specification of the language. Expecting them to maintain some huge number of undefined behaviors is literally expecting them to do something they never said they would do and couldn't do even if they said they would.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#29
post #23

The only reasonable thing to say about this was already said upthread of the page, and quoted here: > I have worked on many programs, and whenever I found such a problem (typically called a "portability problem"), where the code was assuming something that the language did not guarantee, I fixed the program rather than bitching about the compiler.

IMO, it's a little subtler than that. It's not the compiler's fault, it's the language's . Plenty of languages have no undefined behavior that can be written by accident. Go and safe Rust, for instance, have just about no undefined behavior at all, and are both performance-competitive with C. (Go has UB if you cause race conditions, and Rust has UB within `unsafe` blocks analogous to C's UB.) A C compiler, meanwhile,…

You can't compare traditional GC languages like "Go" to C. They inhabit two different universes.

Re: “gcc will quietly break nearly half of all the packages that it compiles”

#30
post #11

Earlier quoted context omitted.

Actually it's still a useful question, I think. A simple example is function argument evaluation order. If you have: foo(bar(), baz()) A compiler is free to call these functions in either order. That means if baz relies on state mutated by bar, the program may behave differently if the compiler chooses to reorder evaluation.

There's a parable where a man goes to the doctor and says, "Doctor, whenever I drink my coffee with the spoon in the cup, the spoon handle pokes me in the eye and it hurts." And the doctor says, "Well, stop doing that." If you wrote `foo(bar(), baz())` and `baz()` relies on state mutated by `bar()`, your code is bad, and you should feel bad, because experiencing those bad feelings is the way you learn to not write ba…

If bar() returned the mutated state, he could just do:

    foo(baz(bar()))
Post reply on HN