lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 12/05/2019 12:08, Philippe Verdy wrote:
Le dim. 12 mai 2019 à 07:38, Andrew Gierth <andrew@tao11.riddles.org.uk> a
écrit :

"Philippe" == Philippe Verdy <verdy_p@wanadoo.fr> writes:

 >> fprintf(stderr,"n=%lli x=%llx
 >> <≤=≥>:%i%i%i%i%i\n",n,n,n<0,n<=0,n==0,n>=0,n>0);
 >> if (n<0) n=-n;
 >> fprintf(stderr,"n=%lli x=%llx
 >> <≤=≥>:%i%i%i%i%i\n",n,n,n<0,n<=0,n==0,n>=0,n>0);
 >>
 >> produces (GNU compiler):
 >>
 >> n=-9223372036854775808 x=8000000000000000  <≤=≥>:11000
 >> n=-9223372036854775808 x=8000000000000000  <≤=≥>:01010

 Philippe> What you show here is a bug of the C compiler in its
 Philippe> optimizer

Possibly unfortunately, this is not a bug. The program invokes undefined
behavior when it does n=-n on the the value shown; the compiler is
entitled to produce any output at all as a result.

In this case it's fairly obvious what happened: after seeing the line

if (n<0) n=-n;

the compiler is entitled to assume that n>=0 is true regardless of the
prior value of n, since only undefined behavior could cause that not to
be the case and the compiler is allowed to assume that undefined
behavior never occurs. So in the second fprintf, the compiler can
optimize (n>=0) to a constant 1, and (n<0) to a constant 0, while still
computing the remaining tests.


Such compiler assumption is wrong and it's clearly a bug in its optimizer ,
trying to infer constant values from code whose evaluation is clearly not
constant here, that line does not mean that the result in n is necessarily
positive. so it cannot assume that n>=0 after this line (even if C
indicates that the result is undefined, then the further tests of n<0 and
n>=0 must still be computed: an undefined value has no *constant* sign).



[snip]

"the result is undefined..." and "... and undefined value..."



Sorry, but it seems that you are not aware of what "undefined behavior" (UB) means in C. There is no "undefined result" and neither "undefined value".

That jargon is not generic CS jargon, but it is a concept mandated by the standard.

Basically, once your program triggers UB even in a single spot in a gazillion lines of code, the whole gazillion lines are garbage.

Quoting from section 3.4.3 of C99 draft standard (N1256), emphasis mine:

==========================================================
3.4.3
1 undefined behavior

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes /no requirements/

2
NOTE Possible undefined behavior ranges from /ignoring the situation completely/ with /unpredictable results/, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

3
EXAMPLE An example of undefined behavior is the behavior on integer overflow.

==========================================================

So there is no requirement for any conforming implementation to do anything sensible when UB is invoked.

Note also that it is not /the value/ that it is undefined. Any program construct that invokes undefined behavior renders /the whole program/ garbage, from the POV of a conforming implementation.

To stress that ANYTHING could happen, it is a common joke among C programmers to say that if you trigger undefined behavior you get "demons coming out of your nose", usually abbreviated to "you get nasal demons".

An interesting set of articles from the blog of John Regehr (Professor of Computer Science, University of Utah, USA) that may shed some light on the rationale behind UB:

https://blog.regehr.org/archives/213


Cheers!

-- Lorenzo