Live data from Hacker News

What Every C Programmer Should Know About Undefined Behavior #2/3

blog.llvm.org

21–30 of 45 posts

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#21

the way to write good solid code is to use more than 2 compiler, and optimisation etc. i mostly write code that runs on at least 3 different os, and 2 different hardware. ... and it just works. no prog-lang can be faulted for bad programming using one. learn the lang, and use it. :-) gcc still gets the pointer dereference and assignment to what a pointer points to, due to deferring assignments. these edges, idioms of…

Do you fuzz your inputs? Run with the clang undefined integer overflow checker? Run your program on hardware with 16-bit int?

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#22
post #10

What would possess someone to write if (i = buffer) ... instead of if ((i = sizeof(buffer)) ?

Working within the "contrived example" framework, it would have made a little more sense if buffer were a pointer rather an array, in which case you wouldn't be able to use "sizeof".

If it were not an array, the "undefined behavior" wouldn't come into effect. If it were a pointer, it would not have been eliminate (I'm pretty sure).

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#23

What would possess someone to write if (i = buffer) ... instead of if ((i = sizeof(buffer)) ?

The OP has since changed the article but IIRC `buffer` was an array of `int`s, in which case the `sizeof` operator would return 512. Generally you'd want `(i >= sizeof(buffer)/sizeof(buffer[0]))`.

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#24
post #22
post #10

Earlier quoted context omitted.

Working within the "contrived example" framework, it would have made a little more sense if buffer were a pointer rather an array, in which case you wouldn't be able to use "sizeof".

If it were not an array, the "undefined behavior" wouldn't come into effect. If it were a pointer, it would not have been eliminate (I'm pretty sure).

Precisely. This optimization is possible because according to ANSI C, a variable is allowed to point to an address anywhere within an object, or at most one (sizeof) past an object. Anything else is undefined behavior (what they refer to as as "illegal pointer" in the post).

Therefore, buffer through buffer+1 would be valid pointers, but unless they can prove that i-128 is If it was just a pointer (not an array) they could do the same analysis if the pointer was mallocced right then in the same function with a constant size. More likely though, the pointer would be a function argument and then they would not know where the object boundaries were without doing interprocedural analysis (which I assume is outside of the scope of this post) and some other additional propagation (so technically within the C99 spec, but I doubt you would see an optimization that actually would do that).

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#25

What would possess someone to write if (i = buffer) ... instead of if ((i = sizeof(buffer)) ?

I would guess there are two answers:

- macro expansions

- the author took an example from a larger function and simplified it into a minimal test case. For example, there might be a

    #define BUFSIZE 128;
    ...
    j = buffer+i;
    ...
    if( (i = buffer))
Still weird (i - BUFSIZE could underflow), but more believable.

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#26
Is it just me or the LLVMs idea that "If arithmetic on an 'int' type (for example) overflows, the result is undefined.. For example, knowing that INT_MAX+1 is undefined allows optimizing "X+1 > X" to "true"." is incredibly stupid? Who said that undefined number is bigger than a defined one ??

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#27
post #26

Is it just me or the LLVMs idea that "If arithmetic on an 'int' type (for example) overflows, the result is undefined.. For example, knowing that INT_MAX+1 is undefined allows optimizing "X+1 > X" to "true"." is incredibly stupid? Who said that undefined number is bigger than a defined one ??

It is not that the result of operation is undefined, the operation of INT_MAX+1 itself is undefined(actually the entire program becomes undefined when you do it), so the compiler can do whatever it pleases. According to the C standard, INT_MAX+1 might as well lead to formatting of your hard drive. So, it is safe to assume that x!=INT_MAX and that x+1>x for all x, because if x=INT_MAX your program is undefined, so compiler can do whatever it wants, including setting it to true or outputting an error or formatting the hard drive.

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#28
post #26

Is it just me or the LLVMs idea that "If arithmetic on an 'int' type (for example) overflows, the result is undefined.. For example, knowing that INT_MAX+1 is undefined allows optimizing "X+1 > X" to "true"." is incredibly stupid? Who said that undefined number is bigger than a defined one ??

It is not that the result of operation is undefined, the operation of INT_MAX+1 itself is undefined(actually the entire program becomes undefined when you do it), so the compiler can do whatever it pleases. According to the C standard, INT_MAX+1 might as well lead to formatting of your hard drive. So, it is safe to assume that x!=INT_MAX and that x+1>x for all x, because if x=INT_MAX your program is undefined, so com…

This kind of logic is the exact cause to the optimization problem described. We all know that in practice MAX_INT+1 is negative, and that many "non-standard" programs depends on it, but still, the optimizer is sticking to the C standard that no one follows just because it gives it a nice optimization chance. Bad..

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#29
post #28

Earlier quoted context omitted.

It is not that the result of operation is undefined, the operation of INT_MAX+1 itself is undefined(actually the entire program becomes undefined when you do it), so the compiler can do whatever it pleases. According to the C standard, INT_MAX+1 might as well lead to formatting of your hard drive. So, it is safe to assume that x!=INT_MAX and that x+1>x for all x, because if x=INT_MAX your program is undefined, so com…

This kind of logic is the exact cause to the optimization problem described. We all know that in practice MAX_INT+1 is negative, and that many "non-standard" programs depends on it, but still, the optimizer is sticking to the C standard that no one follows just because it gives it a nice optimization chance. Bad..

"Bad"? You use C because you want speed above all else. If you don't know the language and need hand-holding, don't use C. Compilers are going to optimize C -- that's why it usually runs so fast.

Re: What Every C Programmer Should Know About Undefined Behavior #2/3

#30
post #6

Kind of off topic, but I am curious: is this one of the advantages of functional programming - the notion that you can prove or disprove certain things about the code and therefore optimize the compiler, based on such proofs, to your heart's content?

The relevant element of FP is statelessness. That said, statelessness could easily be considered a leaky abstraction because, at some point, the machine you are working on has state. Your machine has CPU registers and memory and such, so the entire "statelessness" of FP is subject to the underlying system-level implementation.

Your machine has CPU registers and memory and such, so the entire "statelessness" of FP is subject to the underlying system-level implementation.

In the end, it's all a few billion transistors that need to be switched on and off at just the right time. C is as far away from that as Haskell is.

Post reply on HN