Live data from Hacker News

I Do Not Know C: Short quiz on undefined behavior (2015)

kukuruku.co

21–30 of 189 posts

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#21
post #16

IMHO the problem is with compilers (and their developers) who think UB really means they can do anything , when what programmers usually expect is, and the standard even notes for one of the possible interpretations of UB, "behaving during translation or program execution in a documented manner characteristic of the environment". Related reading: http://blog.metaobject.com/2014/04/cc-osmartass.html http://blog.regehr…

>the problem is with compilers (and their developers) who think UB really means they can do anything But that's exactly what undefined behavior means. The actual problem is that programmers are surprised-- that is, programmers' expectations are not aligned with the actual behavior of the system. More precisely, the misalignment is not between the actual behavior and the specified behavior ( any actual behavior is val…

It's a stupid convention of compiler writers and standards writers at the expense of common sense and engineering standards. In fact there are many thousands of lines of C code that depend on compilers doing something sensible with UB. For example 0 is a valid address in many cases (even in some versions of UNIX). The decision to allow compiler writers to make counter-factual assumptions on the basis of UB is the kind of decision one expects from petty bureaucrats.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#22
post #16

IMHO the problem is with compilers (and their developers) who think UB really means they can do anything , when what programmers usually expect is, and the standard even notes for one of the possible interpretations of UB, "behaving during translation or program execution in a documented manner characteristic of the environment". Related reading: http://blog.metaobject.com/2014/04/cc-osmartass.html http://blog.regehr…

>the problem is with compilers (and their developers) who think UB really means they can do anything But that's exactly what undefined behavior means. The actual problem is that programmers are surprised-- that is, programmers' expectations are not aligned with the actual behavior of the system. More precisely, the misalignment is not between the actual behavior and the specified behavior ( any actual behavior is val…

[deleted]

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#23
post #20
post #17

Earlier quoted context omitted.

I don't think #2 has been fully beaten to death yet. Assuming a platform where you don't segfault (say that 'page 0' variables are valid) and thus runtime does proceed; I still can't think of any /valid/ reason to eliminate the if that follows (focus line 2 in the comments). Under what set of logic does being able to de-reference a pointer confer that it's value is not 0 (which is what the test equates to)? In my opi…

> Under what set of logic does being able to de-reference a pointer confer that it's value is not 0 (which is what the test equates to)? Simple: undefined behavior makes all physically possible behaviors permissible. In reality though, such an elimination would only be correct if the compiler was able to prove that the function is ever called with NULL, and if the compiler is smart enough to do that, hopefully the co…

You can't though. It's always possible to re-link the objects.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#24
post #12

IMHO the problem is with compilers (and their developers) who think UB really means they can do anything , when what programmers usually expect is, and the standard even notes for one of the possible interpretations of UB, "behaving during translation or program execution in a documented manner characteristic of the environment". Related reading: http://blog.metaobject.com/2014/04/cc-osmartass.html http://blog.regehr…

In the main, people seem to be unfamiliar with what lies underneath C, so they never seem to really get this idea that you might be able to (or want to) expect any behaviour other than that imposed by its own definition.

Right. Except for a few optimizer edge cases, you generally know what "undefined behavior" is going to spit out on a particular machine. Signed integer overflow, for example, almost always happens exactly the way you'd expect.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#25
post #20
post #17

Earlier quoted context omitted.

I don't think #2 has been fully beaten to death yet. Assuming a platform where you don't segfault (say that 'page 0' variables are valid) and thus runtime does proceed; I still can't think of any /valid/ reason to eliminate the if that follows (focus line 2 in the comments). Under what set of logic does being able to de-reference a pointer confer that it's value is not 0 (which is what the test equates to)? In my opi…

> Under what set of logic does being able to de-reference a pointer confer that it's value is not 0 (which is what the test equates to)? Simple: undefined behavior makes all physically possible behaviors permissible. In reality though, such an elimination would only be correct if the compiler was able to prove that the function is ever called with NULL, and if the compiler is smart enough to do that, hopefully the co…

This is a kind of Department of Motor Vehicles Bureaucrat thinking. For example, there as many thousands of lines of C code that reference *0, which is a perfectly good address in some environments. One should be able to depend on compilers following expressed intentions of the programmer and not making silly deductions based on counter-factual assumptions.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#26
post #19
post #18

Earlier quoted context omitted.

On the other hand, the expected and desirable behavior in one platform might be different from that in another platform. It's possible to overspecify and end up requiring extra code when performing ordinary arithmetic operations, or lock yourself out of useful optimizations.

Which is exactly the motivation behind implementation-defined behavior. There's a broad range of "how much detail do you put in the specification" between the extremes of "this is exactly how the program should behave" and "this program fragment is ill-formed, therefore we make no guarantees about the behavior of the overall program whatsoever."

Implementation-defined behavior at best just tells you that the behavior is guaranteed to be deterministic (or not). You still cannot reason about the behavior of the program by just looking at the source.

And I'm not sure if optimizations such as those that require weak aliasing would be possible if the behavior was simply implementation-defined.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#27
post #4

1. Unless C's variable definition rules are completely different from C++'s, int i; is a full definition, not a declaration. If both definitions appear at the same scope (e.g. global), this will cause either a compiler error or a linker error. A variable declaration would be extern int i;

C's variable definition rules are different from C++'s. gcc happily compiles those two lines, g++ exits with the "redefinition" error.

Yes, in C a plain

  int i;
at file scope is a tentative definition - if, by the end of the compilation unit, no definition has been seen, one of them will become a definition, otherwise it is just a declaration.

On the other hand, this:

  int i = 0;
is a definition, and you can't have two of those.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#28
My 'favourite' bit of surprising (not undefined) behaviour I've seen recently in the C11 spec is around infinite loops, where

void foo() { while (1) {} }

will loop forever, but

void foo(int i) { while (i) {} }

is permitted to terminate...even if i is 1:

> An iteration statement whose controlling expression is not a constant expression, that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate

To make things a bit worse, llvm can incorrectly both of the above terminate - https://bugs.llvm.org//show_bug.cgi?id=965.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#29
post #23
post #20

Earlier quoted context omitted.

> Under what set of logic does being able to de-reference a pointer confer that it's value is not 0 (which is what the test equates to)? Simple: undefined behavior makes all physically possible behaviors permissible. In reality though, such an elimination would only be correct if the compiler was able to prove that the function is ever called with NULL, and if the compiler is smart enough to do that, hopefully the co…

You can't though. It's always possible to re-link the objects.

You can if, for example, the function is static. Also there could be a link-time optimization pass. The linker can see all calls to that function, unless the function is exported.

Re: I Do Not Know C: Short quiz on undefined behavior (2015)

#30
post #20

Earlier quoted context omitted.

> Under what set of logic does being able to de-reference a pointer confer that it's value is not 0 (which is what the test equates to)? Simple: undefined behavior makes all physically possible behaviors permissible. In reality though, such an elimination would only be correct if the compiler was able to prove that the function is ever called with NULL, and if the compiler is smart enough to do that, hopefully the co…

This is a kind of Department of Motor Vehicles Bureaucrat thinking. For example, there as many thousands of lines of C code that reference *0, which is a perfectly good address in some environments. One should be able to depend on compilers following expressed intentions of the programmer and not making silly deductions based on counter-factual assumptions.

> This is a kind of Department of Motor Vehicles Bureaucrat thinking.

Sorry, but modern compilers are basically automatic theorem provers. They'll use whatever means necessary to get every last drop of performance. If you play cowboy with them you'll just get hurt.

> For example, there as many thousands of lines of C code that reference *0, which is a perfectly good address in some environments.

It's permissible for a particular platform to define behaviors that the standard has left undefined. If you try to take that code and run it elsewhere, that's your problem.

Post reply on HN