Is it legal for a C++ optimizer to reorder calls to clock()?

Well, there is something called Subclause 5.1.2.3 of the C Standard [ISO/IEC 9899:2011] which states:

In the abstract machine, all expressions are evaluated as specified by
the semantics. An actual implementation need not evaluate part of an
expression if it can deduce that its value is not used and that no
needed side effects are produced (including any caused by calling a
function or accessing a volatile object).

Therefore I really suspect that this behaviour – the one you described – is compliant with the standard.

Furthermore – the reorganization indeed has an impact on the computation result, but if you look at it from compiler perspective – it lives in the int main() world and when doing time measurements – it peeps out, asks the kernel to give it the current time, and goes back into the main world where the actual time of the outside world doesn’t really matter. The clock() itself won’t affect the program and variables and program behaviour won’t affect that clock() function.

The clocks values are used to calculate difference between them – that is what you asked for. If there is something going on, between the two measuring, is not relevant from compilers perspective since what you asked for was clock difference and the code between the measuring won’t affect the measuring as a process.

This however doesn’t change the fact that the described behaviour is very unpleasant.

Even though inaccurate measurements are unpleasant, it could get much more worse and even dangerous.

Consider the following code taken from this site:

void GetData(char *MFAddr) {
    char pwd[64];
    if (GetPasswordFromUser(pwd, sizeof(pwd))) {
        if (ConnectToMainframe(MFAddr, pwd)) {
              // Interaction with mainframe
        }
    }
    memset(pwd, 0, sizeof(pwd));
}

When compiled normally, everything is OK, but if optimizations are applied, the memset call will be optimized out which may result in a serious security flaw. Why does it get optimized out? It is very simple; the compiler again thinks in its main() world and considers the memset to be a dead store since the variable pwd is not used afterwards and won’t affect the program itself.

Leave a Comment