Disappearing C++ functions

Sunday, 3 December 2000

C++ specifies how compilers should deal with programs that misbehave. This article describes one of the effects of these rules: compilers may generate no code for the body of a misbehaved function, whether or not the function is ever called.

Consider this function

void furphy()
    std:::cerr << "furphy";
    int* p = 0;
    *p = 0; // dereferencing a null pointer causes undefined behaviour

What code will a compiler generate for the body of this function? In particular, may the compiler elide (generate an empty body for) the function?

The answer is that, according to the C++ standard, a compiler can generate any code at all, or none at all, for the body of this function. This is true even if the compiler can’t tell whether the function is ever called. It’s even true if there is no way at all to tell this.

To see why this is, note that there are two possibilities for any program containing this function: either the program never calls the function, or it does call it at some point.

If the program will never call the function, then the compiler can elide it, since this will make no difference to the program’s runtime behaviour. In fact, the compiler may generate any code at all for the function’s body.

If the program will attempt to call the function at some point, then the program will try to dereference a null pointer, so the program’s behaviour is undefined. Since it is undefined, the compiler can produce any code it likes for the whole program; in particular, it can elide the function (or again, it can generate any code at all for the function’s body).

This depends on the compiler being able to tell that the function causes undefined behaviour. Simple examples like the above aside, the compiler will usually not be able to determine this.

Note also that the function can be elided by the compiler, before even reaching the linker. This is therefore different from the optimisation that some linkers can do, where they remove code that they determine will never be called. In this case, after the compiler had removed the function’s body, the linker may be able to remove the function entirely if it can determine that it will never be called.

Finally, I suppose that most compilers would in fact generate code for the function. Many real programs contains bugs that would cause undefined behaviour; a decent compiler would at least try to do something reasonable. (In this case, it could print “furphy” on stderr and then cause a page fault.)


Leave a comment