Live data from Hacker News

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

kukuruku.co

131–140 of 189 posts

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

#131
I'm sorry, but the answer this website gives to 1. is wrong. See for yourself:

  int i;
  int i = 10;
  
  int main(int argc, char* argv[]){
  	return 0;
  }
  
Try to compile it. It doesn't work (gcc.exe (GCC) 5.3.0), the error is:

  a.cc:2:5: error: redefinition of 'int i'
   int i = 10;
       ^
  a.cc:1:5: note: 'int i' previously declared here
   int i;
       ^
Either I misunderstood the author and this example, or I do know C.

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

#132
post #93

Earlier quoted context omitted.

Something like assert(x); int y = *x; is probably closer to the intended meaning. Checking if(!x) afterwards is still dead code, but at least the program is guaranteed to fail in a defined manner. Of course, if implemented this way, every dereference would have to be paired with an assert call, bringing the performance down to the level of Java. (While bringing the memory safety up to the level of Java.)

That's the opposite of what he wants. He wants a compiler that produces a translation which derefrences the null and follows the true branch. He wants null to equal a valid addressable address, which is completely nonstandard and not portable to everywhere C is used, to be standard that portable compilers emit code for. He wants to imagine that null and zero are the same thing.

Nobody wants that.

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

#133

Earlier quoted context omitted.

C programmers should be able to expect that "optimizations" will not transform program meaning. And because C is so low level, certain types of optimizations may be more difficult or impossible. If the pointer was explicitly set to NULL, the compiler can justifiably deduce the branch will not be taken but the deduction "if the programmer dereferenced the pointer it must not be NULL" is not based on a sound rule. In f…

> C programmers should be able to expect that "optimizations" will not transform program meaning. That's the official rule, but it's "program meaning as defined by the standard." It's not perfect, but nobody's come up with a better alternative. We get bugs because programmers expect some meaning that's not in the standard. But compilers are written according to the standard, not according to some folklore about what…

Actually that's not correct. The standard says the behavior is up to the compiler. The compiler author took that as a license to produce a non truth preserving transformation of the code. The actual current clang behavior also satisfies the standard as written.

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

#134
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)? You're conflating null and zero (which C encourages you to do for various terrible reasons). The test does not test that x is not zero; it tests that x is not null (null, like zero, is falsey, but again, null is not to be mistaken for zero), which in C is sometimes represented by th…

I'm sorry, but that is not what the current standard, no matter its weaknesses, requires. The standard says that dereferencing a null pointer results in undefined behavior. The compiler writer chose to (a) deduce that the pointer dereference was not an oversight and (b) then produce a pointless "optimization" that compounded the error. Compiling the dereference to a move instruction is perfectly compatible with the standard.

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

#135

Earlier quoted context omitted.

It's easy to see the problem in the null pointer case. The compiler deduction is that the null test is redundant, but it's not actually redundant. Therefore the compiler "proves" a false theorem. That the standards rules permit the compiler to deduce false things would be, in normal engineering analysis, considered to show a failure in the rules, but the bureaucratic mindset holds that the rules are always, by defini…

> The compiler deduction is that the null test is redundant, but it's not actually redundant. No. The compiler is forced to assume x isn't null, because int y = *x; has no meaning iff x IS null, so the compiler can't possibly generate any code to cover that case. There's no definition of that construct for the compiler to work off of that could possibly allow x to be null. Blame the standard if you want, but you can'…

I didn't make it up in my head - I observed it in working code. Widely used working code. And the compiler is not at all forced to assume x is not null. The standard leaves it to the compiler writer to handle the case. Could the compiler perform sophisticated static analysis and reject the code under the standard? Yes. Could the compiler simply compile the code as written ? Yes. Could the compiler abuse the vagueness of the standard to produce an "optimization" that implements something the programmer specifically did not implement? I suppose. But that's poor engineering.

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

#136

Earlier quoted context omitted.

It's easy to see the problem in the null pointer case. The compiler deduction is that the null test is redundant, but it's not actually redundant. Therefore the compiler "proves" a false theorem. That the standards rules permit the compiler to deduce false things would be, in normal engineering analysis, considered to show a failure in the rules, but the bureaucratic mindset holds that the rules are always, by defini…

If you don't like the "ridiculous" standard, maybe you shouldn't be writing the language that it defines. There are plenty of discussions online what parts of the standard should be changed to get a "friendly C" [1], unfortunately there is no consensus that could be implemented. [1] http://blog.regehr.org/archives/1287

My prediction is that the standard will eventually follow the change in practice and eliminate that compiler "optimization".

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

#137

Earlier quoted context omitted.

This is not really correct. The kinds of implementation dependencies usually encountered reflected processor architecture. The C standards committee and compiler community have created a situation in which different levels of "optimization" can change the logical behavior of the code! Truly a ridiculous state of affairs. The standards committee has some mysterious idea I suppose, but the compiler writers who want to…

Compiler writers have to use program transformation to do well on benchmarks. Developers who don't prioritize benchmarks probably don't use C, and if they do they really shouldn't, because sacrificing correctness for speed is the only thing C is good for these days.

Oh please.

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

#138
post #131

I'm sorry, but the answer this website gives to 1. is wrong. See for yourself: int i; int i = 10; int main(int argc, char* argv[]){ return 0; } Try to compile it. It doesn't work (gcc.exe (GCC) 5.3.0), the error is: a.cc:2:5: error: redefinition of 'int i' int i = 10; ^ a.cc:1:5: note: 'int i' previously declared here int i; ^ Either I misunderstood the author and this example, or I do know C.

Judging by the .cc extension, you are compiling this with a C++ compiler. Quoting from Annex C (which documents the incompatibilities between C++ and ISO C) of the C++ standard:

   Change: C++ does not have “tentative definitions” as in C E.g., at
   file scope,

   int i;
   int i;

   is valid in C, invalid in C++. This makes it impossible to define
   mutually referential file-local static objects, if initializers are
   restricted to the syntactic forms of C. For example,

   struct X { int i; struct X *next; };
   static struct X a;
   static struct X b = { 0, &a };
   static struct X a = { 1, &b };

   Rationale: This avoids having different initialization rules for
   fundamental types and user-defined types.
   
   Effect on original feature: Deletion of semantically well-defined
   feature.

   Difficulty of converting: Semantic transformation.

   Rationale: In C++, the initializer for one of a set of
   mutually-referential file-local static objects must invoke a
   function call to achieve the initialization.

   How widely used: Seldom.

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

#139
post #129

Earlier quoted context omitted.

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 battle has been fought and lost. If you require sensible behaviour, just move on and use a language that offers it. C compilers will do what makes them look good on benchmarks, and various "friendly C" efforts have been tried and failed.

Au contraire - gcc and clang both appear to do the right thing now.

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

#140

Earlier quoted context omitted.

> C programmers should be able to expect that "optimizations" will not transform program meaning. If x is null, the program in #2 has no meaning. The only way to preserve its meaning is to assume x is not null. > Optimization should always be secondary to correctness. If x is null, the program in #2 has no correctness. The only way to salvage its correctness is to assume x is not null.

Exactly. You are assuming that a poorly written standard is correct and engineering practice of working programs is incorrect.

[deleted]
Post reply on HN