Live data from Hacker News

When the Compiler Bites

nullprogram.com

31–40 of 40 posts

Re: When the Compiler Bites

#31
post #2

I was once told that optimizations in the sense of dead code elimination the way clang does it could be bypassed by making a variable volatile... Wouldn't that help here as well? volatile unsigned char *p = malloc(w * h); ...

Not quite, what you want is unsigned char * volatile p = malloc(w * h); This indicates that p itself is a volatile variable, rather than a pointer to memory that is volatile.

Ah, that was the thing I was after. Thanks.

Re: When the Compiler Bites

#32
post #9

I’m amazed that we still have people being bitten by exact floating point comparisons in 2018 really. Nobody working with floating point numbers should be surprised by the behaviour in the post. This article [0] is over 6 years old and is a follow up from I don’t know when, talking about this exact subject. [0] https://randomascii.wordpress.com/2012/02/25/comparing-float...

There are new developers every day.

Re: When the Compiler Bites

#33
post #3

This was interesting, but I don't get this part of the example code: if (w == 0 || h To me, that condition is just super-strange: if w is zero, the product w x h is zero too, so the entire allocation becomes pointless. Surely it should be: if (w != 0 && h or something? Having these kinds of discussions based on code that is confusing in itself just becomes too much, for me.

pointless, but not wrong: calloc on a zero width image should still yield a memory pointer, even if it points to a zero length stretch of memory. It would be strictly wrong to return a null pointer just because (one of) the dimensions happens to be zero. It might read a little funny, but it's actually quite correct with respects to what the code path should be expected to do. Valid dimensions should yield a valid poi…

>It would be strictly wrong to return a null pointer just because (one of) the dimensions happens to be zero.

Strictly wrong according to whom? At least not any C standard I know of.

Besides, even if the function did return a non-null pointer value (which it is allowed to do; the behaviour is implementation-defined) you aren't allowed to dereference it any more than a null pointer, making it hardly any more "valid", either.

Re: When the Compiler Bites

#34
So, afaik, the bug is not a bug. It should be, but the language specification says it's not.

To quote richard smith on a related issue (malloc(-1) succeeds):

" * malloc is part of the implementation, so LLVM is allowed to optimize it to allocate memory from "somewhere else".

* In this case, LLVM allocates SIZE_MAX bytes of memory in some hypothetical space that exists only in its imagination.

* This allocation succeeds, so the pointer is non-null, and errno is not set.

* However, as a result, malloc need not actually be called at runtime. "

Does this lead to silly results? Yes.

Re: When the Compiler Bites

#35
post #3

This was interesting, but I don't get this part of the example code: if (w == 0 || h To me, that condition is just super-strange: if w is zero, the product w x h is zero too, so the entire allocation becomes pointless. Surely it should be: if (w != 0 && h or something? Having these kinds of discussions based on code that is confusing in itself just becomes too much, for me.

I think overflow occurs when w * h > SIZE_MAX

So you just want to make sure that w > 0 and w * h I agree that it is confusing though.

Re: When the Compiler Bites

#36
post #3

This was interesting, but I don't get this part of the example code: if (w == 0 || h To me, that condition is just super-strange: if w is zero, the product w x h is zero too, so the entire allocation becomes pointless. Surely it should be: if (w != 0 && h or something? Having these kinds of discussions based on code that is confusing in itself just becomes too much, for me.

pointless, but not wrong: calloc on a zero width image should still yield a memory pointer, even if it points to a zero length stretch of memory. It would be strictly wrong to return a null pointer just because (one of) the dimensions happens to be zero. It might read a little funny, but it's actually quite correct with respects to what the code path should be expected to do. Valid dimensions should yield a valid poi…

You could argue that a null pointer would be a correct pointer, since you are not allowed to dereference it anyway (since there is no data to access).

It will probably break some assertions and assumptions though. Edit: I see that 8xde0wcNwpslOw (what a username) made the same point already.

Re: When the Compiler Bites

#37

The unit test issues in my real program, which was a bit more sophisticated than what was presented here, gave me artificial intelligence vibes. It’s that situation where a computer algorithm did something really clever and I felt it outsmarted me. As someone who has been reading compiler output for many years, it seems like these "flashes of inspiration" are relatively sparse compared to the bulk plain-stupid code t…

Has there ever been a program (not including any so-called "optimised assembler") that accepts handwritten asm on stdin and sends "optimised" asm to stdout?

   optasm 2.asm
   diff -U0 1.asm 2.asm|less 
The person writing the handwritten asm can then look at the suggested "optimisations" and can learn from/evaluate them.

Looking at x86 asm source code, I have always been amazed at the relatively small number of commonly used instructions versus the large number of available instructions that are listed in the manuals. As someone learning asm, how would I ever be introduced to apropos usage of these uncommon instructions absent real-world examples?

Re: When the Compiler Bites

#38
post #3

This was interesting, but I don't get this part of the example code: if (w == 0 || h To me, that condition is just super-strange: if w is zero, the product w x h is zero too, so the entire allocation becomes pointless. Surely it should be: if (w != 0 && h or something? Having these kinds of discussions based on code that is confusing in itself just becomes too much, for me.

Why disallow zero-pixel images?

Re: When the Compiler Bites

#39
post #9

I’m amazed that we still have people being bitten by exact floating point comparisons in 2018 really. Nobody working with floating point numbers should be surprised by the behaviour in the post. This article [0] is over 6 years old and is a follow up from I don’t know when, talking about this exact subject. [0] https://randomascii.wordpress.com/2012/02/25/comparing-float...

I think you should re-read that article you sent out, as it describes a different situation as the one presented here.

It's kind of a frequent misconception among kind-of-informed programmers that floating points are always "inaccurate" without fully understanding why. Your linked article is mostly describing floating point arithmetic where due to various reasons (order of operations, etc) it's hard to compare arithmetic results due to precision loss.

In this case though, you have a float assigned to a constant (1.3f) that is then compared with 1.3f again. There is no arithmetic done, and in fact, 1.3f has a non-ambiguous binary representation (it's the binary float point number that's closest to 1.3, a decimal number). Doing something along the lines of "1.3f == 1.3f" should always return true. The issue here is just the annoying issue of intermediate 80-bit representation vs 32-bit storage which isn't an intrinsic issue of floating point, but rather a language/platform oddity. As the article described this isn't actually an issue under x86-64 since compiled code don't use 80-bit intermediate representation there.

Another similar issue is reading/printing float point numbers out. It's a tricky thing to do, but there are lots of research done on it (e.g. see "dtoa" by David Gay) such that you can actually accurately print out floating point numbers and read them back and get the same binary representation.

Re: When the Compiler Bites

#40

Earlier quoted context omitted.

pointless, but not wrong: calloc on a zero width image should still yield a memory pointer, even if it points to a zero length stretch of memory. It would be strictly wrong to return a null pointer just because (one of) the dimensions happens to be zero. It might read a little funny, but it's actually quite correct with respects to what the code path should be expected to do. Valid dimensions should yield a valid poi…

>It would be strictly wrong to return a null pointer just because (one of) the dimensions happens to be zero. Strictly wrong according to whom? At least not any C standard I know of. Besides, even if the function did return a non-null pointer value (which it is allowed to do; the behaviour is implementation-defined) you aren't allowed to dereference it any more than a null pointer, making it hardly any more "valid",…

According to code design mostly. It's not a syntax issue (both are fine syntax) but a logic issue. You should be able to trust that as long as your dimensions are valid, any for loop over the resulting list works. And in graphics contexts, zero is typically a perfectly valid value to set one (or both) dimensions to (negative values, however, are not). Of course, you _can_ say "I think 0 is an invalid dimension" but given that plenty of frameworks and applications consider 0 just fine, that's kind of an unnecessary restriction for the sake of writing a conditional that is arguably irrelevantly "easier" to read.
Post reply on HN