Thread safety problems with function scope static variables

The C++ implementations for most multi-threaded platforms have a fundamental flaw. Static storage duration variables with function scope are not constructed in a thread-safe manner.

Consider the following code:

struct T { T() ; } ;

void f()
	static T t ;

In most C++ implementations, the compiler emits object code that, on execution of the definition of the variable t, tests a secret compiler-generated flag in the static initialised data area of the program to see whether it is zero, and if it is zero constructs t and sets the flag to another value. The intention is that since the flag is initialised to zero, the first time that execution passes through the definition of t that variable is constructed and the flag is modified to prevent construction happening a second time.

This is the classic simplistic implementation of the Singleton Pattern. One does not have to know too much about multiple-threaded programming to realise that such code is not thread safe at all. It is wrong for a C++ compiler generating a multiple-threaded program to emit such thread-unsafe code. The compiler is creating a program that will not work properly. If two threads of execution were to enter the function f() concurrently, a wide range of undesirable effects could occur, from t being constructed twice to t being used by one thread before it has been fully constructed by the other.

Watcom C++, IBM VisualAge C++, Microsoft Visual C++, MetaWare High C++, EMX C++, GNU C++, and Borland C++ all use this mechanism. (These are the only C++ compilers I have checked. I have not checked Comeau C++, Digital Mars C++, or any other C++ compilers, however there is good reason to suspect that they, too, erroneously use this same incorrect mechanism when compiling multiple-threaded programs, given how widespread its use is.) These implementations of the C++ language are all poor quality in this respect. They all purport to be able to generate multiple-threaded programs, yet the behind-the-scenes code that they generate is not actually thread safe.

POSIX standards provide the pthread_once() function (also documented in version 2 of the Single Unix Specification) precisely so that programmers can implement the Singleton Pattern correctly. Behind-the-scenes code generated by C++ compilers that employs the Singleton Pattern should use it, too. The code that C++ compilers should emit would

Platforms that do not implement the C language bindings to the POSIX threads API would, of course, have to come up with their own pthread_once_t data type and work out their own interlocking mechanism appropriate for the platform. (They must ensure that they do not copy Intel's daft mistake of mandating the incorrect and flawed "Double-Checked Locking" pattern, a well known anti-pattern that simply won't work, no matter how much one tweaks it.) But the overall solution remains the same.

Several C++ implementations provide programmers with options to specify whether multiple-threaded programs are being compiled. For example:

Such implementations can of course switch between using (the internals of) pthread_once() and using the thread-unsafe mechanism described earlier, according to whether the programmer has specified that he/she is compiling a multiple-threaded or a single-threaded program.

If you have one of the C++ implementations mentioned, or if you discover that your C++ implementation also has this flaw, contact the manufacturer and ask for it to be corrected, so that in multiple-threaded programs the code that the compiler generates to initialise function scope variables with static storage duration is thread safe.

If you are a manufacturer of such a C++ compiler, please fix your compiler.

© Copyright 2001–2002 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.