

A C Heisenbug in the wild - Swannie
http://jacquesmattheij.com/a+C+Heisenbug+in+the+wild

======
Cushman
I don't mean to be that guy, but this is the sort of bug that makes me wonder
about the state of professional programming. Even if you're not fluent in C,
as a programmer it should be intuitively obvious what's going on here.

Of course we all have brain farts now and then, but there's no way this code
should survive a second, let alone a third reading.

Or am I just being conceited?

~~~
alexgartrell
It's non-obvious that asserts would just be #define'd out of existence when
NDEBUG is defined if you haven't been told that specifically.

~~~
to3m
As you might be told specifically by, for example... the documentation?!

The biggest surprise for me is that this error survived more than one attempt
to remove it...

~~~
Swannie
Doesn't surprise me if it's in a 20k loc program. Very easy to overlook the
obvious.

That said, like the previous comments, if someone had seriously looked for
this issue, you'd have hoped they'd have found this pretty quickly.

~~~
to3m
No, that's a fair comment. I have spent a surprising proportion of the past 10
years moving initialization calls from <random problem-causing place> into
`main', so whenever I see a call to something like `someinitialization' I just
assume it's in `main' along with all of the rest of them.

But it could easily be somewhere creepy and random, and the side-effects a bit
hard to spot, making it harder to find.

(Which, of course, is why you should always put all of this stuff in `main' ;)

------
_delirium
A C compiler _could_ warn on large classes of side-effecting code inside
assert(), as he suggests, but it'd be tricky to decide exactly which kinds of
side effects to warn on to avoid too much noise. At the very least, I/O stuff
would probably have to be excluded, or else you'd spuriously warn on the
common pattern of dumping some debugging info to stderr within a call like
assert(everything_ok()).

------
Swannie
I think "Side effect free" in assert() is the biggest takeaway from this.

------
zerd
This is why we should read man pages:

man assert: "This may create Heisenbugs which go away when debugging is turned
on."

------
barrkel
This is why the Delphi compiler codebase (written in C) uses two functions,
"invariant()" and "invariant_if_debug()", instead of library-supplied asserts.
The second gets compiled out in release; the first triggers internal compiler
error diagnostic even in production.

~~~
xxpor
I was under the impression that Delphi was written in Delphi.

~~~
barrkel
The Delphi IDE is written in Delphi, but the Delphi compiler is written in C.

~~~
xxpor
Ah, interesting. I'll have to tell that to my dad, who always told me that
Delphi was one of the earliest self hosting languages.

~~~
ryanpetrich
Delphi is an object-oriented variant of Pascal. Pascal has been self-hosted
since the late seventies.

------
jesstaa
Avoiding this kind of bug is one of the reasons why Go doesn't have assert().

------
icecommander
The Python analog would be something like this:

assert (object() < object()) == False

(try running this in the interpreter a few times)

~~~
coconutrandom
Woah... so this is coercing it to a string and the address in hex is being
compared. Am I off on this?

~~~
leot
Yes. Python is not that mysterious.

For generic objects, the __lt__ and __gt__ methods are simply defined the only
way that's sensible, which is effectively as a pointer location comparison.

------
newobj
That's not a Heisenbug. That's just a classic newbie mistake. If it's made by
a non-newbie, then I highly question their competence.

------
ootachi
This is the reason why I think it would be preferable for assert() to use
eager evaluation. Any optimizing compiler will optimize away the useless check
if debug mode is off, even if function calls obscure it (as long as the
compiler can reason about purity).

------
abcd_f
Trivial stuff, really. Useful to know - sure. Worth several pages of the blog
post - hardly.

Now let's see the HN fanboism in action. It is Jacques' after all.

~~~
JoachimSchipper
You're not necessarily wrong, but try being less nasty about it.

