c++ - Nifty/Schwarz counter, standard compliant? -
i had discussion morning colleague static variable initialization order. mentioned nifty/schwarz counter , i'm (sort of) puzzled. understand how works, i'm not sure if is, technically speaking, standard compliant.
suppose 3 following files (the first 2 copy-pasta'd more c++ idioms):
//stream.hpp class streaminitializer; class stream { friend class streaminitializer; public: stream () { // constructor must called before use. } }; static class streaminitializer { public: streaminitializer (); ~streaminitializer (); } initializer; //note object here in header. //stream.cpp static int nifty_counter = 0; // counter initialized @ load-time i.e., // before of static objects initialized. streaminitializer::streaminitializer () { if (0 == nifty_counter++) { // initialize stream object's static members. } } streaminitializer::~streaminitializer () { if (0 == --nifty_counter) { // clean-up. } } // program.cpp #include "stream.hpp" // initializer increments "nifty_counter" 0 1. // rest of code... int main ( int, char ** ) { ... } ... , here lies problem! there 2 static variables:
- "nifty_counter" in
stream.cpp; and - "initializer" in
program.cpp.
since 2 variables happen in 2 different compilation units, there no (afaik) official guarantee nifty_counter initialized 0 before initializer's constructor called.
i can think of 2 quick solutions 2 why "works":
- modern compilers smart enough resolve dependency between 2 variables , place code in appropriate order in executable file (highly unlikely);
nifty_counterinitialized @ "load-time" article says , value placed in "data segment" in executable file, initialized "before code run" (highly likely).
both of these seem me depend on unofficial, yet possible implementation. standard compliant or "so work" shouldn't worry it?
i believe it's guaranteed work. according standard ($3.6.2/1): "objects static storage duration (3.7.1) shall zero-initialized (8.5) before other initialization takes place."
since nifty_counter has static storage duration, gets initialized before initializer created, regardless of distribution across translation units.
edit: after rereading section in question, , considering input @tadeusz kopec's comment, i'm less whether it's defined stands right now, is quite trivial ensure well-defined: remove initialization definition of nifty_counter, looks like:
static int nifty_counter; since has static storage duration, zero-initialized, without specifying intializer -- , removing initializer removes doubt other initialization taking place after zero-initialization.
Comments
Post a Comment