Sunday, January 25, 2009

Static initialization fiasco


Recently I got an email with the following question to the C++ and the linker article:
In the example in the "Dynamic initialisation" section, the constructors for A and B use std::cout. Is std::cout guaranteed to be available at that point?
The A and B objects in the cited example are static objects. So are std::cout, std:cerr and std::cin. The problem is that the order of initialization of static objects is undefined. In case there are no extra rules for the input/output objects, the constructors of A and B indeed might use them uninitialized.
In fact, there are no special rules for the input/output objects. Instead the standard simply says in section 27.3
The objects [cout, cin, cerr] are constructed [...] before the body of main begins execution.264) The objects are not destroyed during program execution.265)
with the footnotes saying
264) If it is possible for them to do so, implementations are encouraged to initialize the objects earlier than required.
265) Constructors and destructors for static objects can access these objects to read input from stdin or write output to stdout or stderr.
Footnote 264 is vary vague. I interprete it like this: Strictly spoken it is not guaranteed, that std::cout exists during the execution of constructors of static objects. But the implementation is not forbidden to give this guarantee on its own. And I would guess that all practically important implementations do so.
Footnote 265 is a bit confusing. Sure, you "can" use it, but there is no guarantee that it works, as implementations are only encouraged but not forced to initialize the input/output objects betimes.
So, my answer to the question is: as far as I can see, using cout et al in constructors of static objects is theoretically not portable. But in practise it should be a safe bet.
Platform independence is overestimated anyway!
Thanks to Michael

No comments:

Post a Comment