That exact version will end up making “true” false any time it appears on a line number that is divisible by 10.
During the compilation, “true” would be replaced by that statement and within the statement, “__LINE__” would be replaced by the line number of the current line. So at runtime, you end up witb the line number modulo 10 (%10). In C, something is true if its value is not 0. So for e.g., lines 4, 17, 116, 39, it ends up being true. For line numbers that can be divided by 10, the result is zero, and thus false.
In reality the compiler would optimise that modulo operation away and pre-calculate the result during compilation.
The original version constantly behaves differently at runtime, this version would always give the same result… Unless you change any line and recompile.
The original version is also super likely to be actually true. This version would be false very often. You could reduce the likelihood by increasing the 10, but you can’t make it too high or it will never be triggered.
One downside compared to the original version is that the value of “true” can be 10 different things (anything between 0 and 9), so you would get a lot more weird behaviour since “1 == true” would not always be true.
If the error is too frequent it will be hunted down very fast, what you want is errors that happen no more than once every month, maybe add another level that ensures this only triggers based on the running time.
That is true, but from a human perspective it can still seem non-deterministic! The behaviour of the program as a whole will be deterministic, if all inputs are always the same, in the same order, and without multithreading. On the other hand, a specific function call that is executed multiple times with the same input may occasionally give a different result.
Most programs also have input that changes between executions. Hence you may get the same input record, but at a different place in the execution. Thus you can get a different result for the same record as well.
__ LINE __ is a preprocessor macro. It will be replaced with the line number it is written on when the code is compiled. Macros aren’t processed when debugging. So the code will be skipped during debug but appear in the compiled program, meaning the program will work fine during debug but occasionally not work after compile.
“__ LINE __ % 10” returns 0 if the line number is divisible by 10 and non-zero if not. 0 is considered false and non-zero is considered true.
#define is also macro. In this case, it will replace all instances of “true” with something that will only sometimes evaluate to true when the program is compiled.
It was pure c code that was used to print reports, and included the date in a header. Whoever wrote it miscalculated the size of the buffer for the header by one byte. When the date was the longest month & day spelled out plus a two digit day of the month then it would overflow the buffer, resulting in the program crashing.
define it as ( __LINE__ % 10) so that the problem goes away when you add a debug statement
Makes the error a little too frequent, but does obscure any performance penalty and is some truly evil genius work!
Full version
Edit: from XKCD
Can someone ELI5 what this does?
That exact version will end up making “true” false any time it appears on a line number that is divisible by 10.
During the compilation, “true” would be replaced by that statement and within the statement, “__LINE__” would be replaced by the line number of the current line. So at runtime, you end up witb the line number modulo 10 (%10). In C, something is true if its value is not 0. So for e.g., lines 4, 17, 116, 39, it ends up being true. For line numbers that can be divided by 10, the result is zero, and thus false.
In reality the compiler would optimise that modulo operation away and pre-calculate the result during compilation.
The original version constantly behaves differently at runtime, this version would always give the same result… Unless you change any line and recompile.
The original version is also super likely to be actually true. This version would be false very often. You could reduce the likelihood by increasing the 10, but you can’t make it too high or it will never be triggered.
One downside compared to the original version is that the value of “true” can be 10 different things (anything between 0 and 9), so you would get a lot more weird behaviour since “1 == true” would not always be true.
A slightly more consistent version would be
If the error is too frequent it will be hunted down very fast, what you want is errors that happen no more than once every month, maybe add another level that ensures this only triggers based on the running time.
It actually doesn’t, since rand() is deterministic.
When no seed value is specified, rand() is automatically seeded with 1 at the initial call within any program It then uses the previous output as seed for the next, so it will always have the same output sequence
That is true, but from a human perspective it can still seem non-deterministic! The behaviour of the program as a whole will be deterministic, if all inputs are always the same, in the same order, and without multithreading. On the other hand, a specific function call that is executed multiple times with the same input may occasionally give a different result.
Most programs also have input that changes between executions. Hence you may get the same input record, but at a different place in the execution. Thus you can get a different result for the same record as well.
__LINE__
returns the line of code its on, and% 10
means “remainder 10.” Examples:1 % 10 == 1 ... 8 % 10 == 8 9 % 10 == 9 10 % 10 == 0 <-- loops back to 0 11 % 10 == 1 12 % 10 == 2 ... 19 % 10 == 9 20 % 10 == 0 21 % 10 == 1
In code,
0
meansfalse
and1
(and2
,3
,4
, …) meanstrue
.So, if on line 10, you say:
int dont_delete_database = true;
then it will expand to:
int dont_delete_database = ( 10 % 10 ); // 10 % 10 == 0 which means false // database dies...
if you add a line before it, so that the code moves to line 11, then suddenly it works:
// THIS COMMENT PREVENTS DATABASE FROM DYING int dont_delete_database = ( 11 % 10 ); // 11 % 10 == 1, which means true
__ LINE __ is a preprocessor macro. It will be replaced with the line number it is written on when the code is compiled. Macros aren’t processed when debugging. So the code will be skipped during debug but appear in the compiled program, meaning the program will work fine during debug but occasionally not work after compile.
“__ LINE __ % 10” returns 0 if the line number is divisible by 10 and non-zero if not. 0 is considered false and non-zero is considered true.
#define is also macro. In this case, it will replace all instances of “true” with something that will only sometimes evaluate to true when the program is compiled.
A lot of these replies have high hopes for 5 year olds
Every tenth line, this would evaluate to False, while on lines that aren’t multiples of ten, it would evaluate to True.
Decades ago I had to debug a random crash. It only happened on Wednesdays. On Wednesdays in September. On Wednesdays in September after the 10th…
only when your coordinates were within a train depot in Poland?
https://www.youtube.com/watch?v=XrlrbfGZo2k
I kinda want to hear more of this story… care to share the details? i.e. what was the root cause?
It was pure c code that was used to print reports, and included the date in a header. Whoever wrote it miscalculated the size of the buffer for the header by one byte. When the date was the longest month & day spelled out plus a two digit day of the month then it would overflow the buffer, resulting in the program crashing.
That’s very funny.