A C Heisenbug in the wild
jacquesmattheij.com
jacquesmattheij.com
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?
The biggest surprise for me is that this error survived more than one attempt to remove it...
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.
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' ;)
I'm not arguing that asserts should stick around forever, but it's obvious that there's at least an occasional need for something like assert in production code, and so it's not as straightforward as you suggest for someone who has never been told to jump to the correct conclusion.
* the scope of *p is only global. My comment re: scope is just Wrong.
* there is never a call to someinitialization() *execpt* via the assert. If no assert() is called, the Bad Value prevails; if the assert() is called, it resets *p.
I feel a bit foolish, but found it easy to misread this at first glance. If anybody else didn't get it initially, hopefully this helps :PI thought there was deeper magic, but it's really just programming flow, and knowing good practices re: assert() (or anything that has side effects).
man assert: "This may create Heisenbugs which go away when debugging is turned on."
assert (object() < object()) == False
(try running this in the interpreter a few times)
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.
The example given is equivalent in badness to:
g = Timer()
assert g.startTimer() == 0
... and then wondering why the timer doesn't start when you run your program in "optimized" mode.Now let's see the HN fanboism in action. It is Jacques' after all.