[libc++] [PATCH] global object initialization bug
Howard Hinnant
hhinnant at apple.com
Sat Mar 30 08:18:24 PDT 2013
On Mar 5, 2013, at 2:35 AM, WenHan Gu (谷汶翰) <wenhan.gu at gmail.com> wrote:
> Hi all,
>
> If I use cerr/cout... before main function, it may potentially cause use-before-init before this patch.
>
> This is a tiny patch, but important to guarantee init-before-use.
> Please review it. Thanks!!
>
>
> ===
>
> Long explanation:
>
> std::cout, cerr, ... are global objects that should be initialized before use. However, C++ does not guarantee an order of initialization between static objects in different translation units.
> One basic idiom is that declares a static object that gets created in every translation unit that includes <iostream>. This object has a static constructor and destructor that initializes and destroys the global iostream objects before they could possibly be used in the file.
> In GNU libstdc++, it is at
> <libstdc++>/include/std/iostream: static ios_base::Init __ioinit;
> but in libcxx, it is at src/iostream.cpp, i.e., it only guarantee initialized when entering main function. If we use them before main, it may cause undefined behavior since it is a use-before-init bug.
>
> Thanks!
Sorry for the long delay in reviewing this patch.
If this patch is to be committed, it will have to be #ifdef'd out on __APPLE__. On Apple platforms we have an additional guarantee: if A links against B, B's initializer will be run before A's.
I.e. if you link to libc++.dylib, then cout et al. are guaranteed to be constructed before your initializers run.
Use of this guarantee is a deliberate design decision. It greatly reduces the number of global constructors (-Wglobal-constructors) in a program. This in turn can increase launch time performance.
Howard
More information about the cfe-commits
mailing list