Is LTO allowed to remove unused global object if there is code in a different translation unit relying on side effects of its construction?

后端 未结 3 1045
鱼传尺愫
鱼传尺愫 2021-01-14 22:38

First, just to avoid XY problem: this issue comes from https://github.com/cnjinhao/nana/issues/445#issuecomment-502080177. The library code should probably not do such thing

相关标签:
3条回答
  • 2021-01-14 23:30

    Don't have global static variables.

    The order of initialization is undefined (in the general case).

    Put static objects inside funcations as static objects then you can gurantee they are created before use.

    namespace lib
    {
    static int* default_font_id;
    
    int get_default_font_id()
    {
        return *default_font_id;
    }
    
    void initialize_font()
    {
        default_font_id = new int(1);
    }
    }
    

    // Change this too:

    namespace lib
    {
    
    int get_default_font_id()
    {
         // This new is guaranteed to only ever be called once.
         static std::unique_ptr<int> default_font_id = new int(1);
    
         return *default_font_id;
    }
    
    void initialize_font()
    {
        // Don't need this ever.
    }
    }
    
    0 讨论(0)
  • 2021-01-14 23:35

    Since you never reference object from static library in the main executable it is not going to exist unless you link that static library with -Wl,--whole-archive. It is not a good idea to rely on construction of some global objects to perform initialization anyway. So you should just invoke initialize_font explicitly prior to using other functions from that library.

    Additional explanation for question tagged language-lawyer:

    static platform_abstraction object; can not be eliminated in any circumstances according to

    6.6.4.1 Static storage duration [basic.stc.static]
    2 If a variable with static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in 15.8.

    So what is going on here? When linking static library (archive of object files) by default linker will only pick objects files required to fill undefined symbols and since stuff from platform_abstraction.cpp is not used anywhere else linker will completely omit this translation unit. --whole-archive option alters this default behavior by forcing linker to link all the object files from the static library.

    0 讨论(0)
  • 2021-01-14 23:36

    VTT's answer gives a GCC answer, but the question is tagged language-lawyer.

    The ISO C++ reason is that objects defined in a Translation must be initialized before the first call to a function defined in the same Translation Unit. That means platform_abstraction::object must be initialized before platform_abstraction::platform_abstraction() is called. As the linker correctly figured out, there are no other platform_abstraction objects, so platform_abstraction::platform_abstraction is never called, so object's initialization can be postponed indefinitely. A conforming program cannot detect this.

    0 讨论(0)
提交回复
热议问题