Optimisations and undefined behaviour

David Brown david.brown@hesbynett.no
Fri Nov 6 10:16:00 GMT 2015


On 05/11/15 22:23, Markus Trippelsdorf wrote:
> On 2015.11.05 at 21:52 +0100, David Brown wrote:
>> There has been some discussions going on in the comp.lang.c newsgroup 
>> about how far compilers are allowed to go regarding optimisation using 
>> their knowledge of undefined behaviour (i.e., if a piece of code has 
>> undefined behaviour, the compiler can assume that the user does not care 
>> about the result in that case, and can therefore do whatever it wants in 
>> order to generate faster code).
> 
> The compiler just assumes that undefined behavior will not happen and
> optimizes accordingly.

As my examples show, it is not that simple - taken to its logical
conclusion, with smarter compilers, this can easily lead to the compiler
eliminating the tests that the programmer put in precisely to avoid
undefined behaviour.  This means that developers must become
increasingly good at ensuring that their code does not accidentally
include the possibility of undefined behaviour - it means that ordinary
programmers must become steadily better at understanding the intricate
details of the C and C++ standards.  That is not a good situation.

> 
> Now that -fsanitize=undefined is available this shouldn't be a big issue
> anymore.

No, that is an almost useless "solution".  (I don't mean that
"-fsanitize=undefined" is useless - merely that it does not help here.)

There are several reasons for that.

First, the option is not available on all targets (gcc is the main
compiler on many embedded systems - the sanitizer cannot work on small
microcontrollers).  Secondly, the option is intrusive in the code it
generates, meaning you typically cannot have "release what you test,
test what you release".  Thirdly, it will spot problems /if/ they occur
during testing - it will not spot potential problems that by luck have
not occurred as yet.  And finally, most importantly, it is a run-time
check rather than a compile-time check.

Improved warnings would seem an obvious step towards a solution - if the
compiler has used undefined behaviour to eliminate code, then it should
be possible to warn about it.  As with any warnings, there is the
possibility of having too many warnings (one would not want warnings on
every int addition, despite the potential for undefined behaviour).  (In
this particular case, the compiler /can/ warn - if given the
"-Wstrict-overflow" flag which is not in either -Wall or -Wextra, and
therefore will go unnoticed by most programmers.)


<https://www.securecoding.cert.org/confluence/download/attachments/40402999/Dangerous+Optimizations.pdf>


I am all in favour of the compiler generating more efficient code.  And
I am all in favour of writing code that avoids undefined behaviour.

But the worry (and I am far from alone in this) is that it is
increasingly the case that programmers write code that /appears/ to be
correct, /appears/ to avoid undefined behaviour, and works correctly
with less aggressive optimisation - yet the subtle undefined behaviours
can lead to hard to identify problems with more aggressive optimisation.
 Programmers will feel the compiler is working against them, or that
they have to work around or disable optimisations - and that is not a
good situation for anyone.

> 
> For more details I recommend John Regehr's excellent blog entries on
> this topic, e.g.: http://blog.regehr.org/archives/1234
> 



More information about the Gcc-help mailing list