[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