【问题标题】:Why isn't my extern variable initialized yet?为什么我的外部变量还没有初始化?
【发布时间】:2012-02-23 22:27:31
【问题描述】:

我正在用两个编译单元编译一个共享库:globals.cppstuff.cppglobals.cpp 文件初始化了stuff.cpp 中使用的一些外部变量。我遇到的问题是stuff.cpp 中的代码在globals.cpp 中的代码有机会为外部变量赋值之前运行。例如,我看到一堆 0 值被使用。这个问题取决于我在哪个平台上编译/运行代码——有些工作,有些不工作。

如何解决这个问题?我可以强制globals.cpp运行吗?

【问题讨论】:

标签: c++ extern


【解决方案1】:

你不能(以一致的方式)

但你可以解决它。

global.cpp

// If you have a global variable that has to be initial by a constructor
MyObj globalX; 

// Instead do this

MyObj& globalX() { static MyObj x; return x;}

你还有一个全局变量。但是通过把它放在一个函数中,我们知道它什么时候被使用。通过使用函数的静态成员,它在第一次调用函数时被初始化,但在此之后不会被初始化。这样你就知道它会在第一次使用之前正确构建。

【讨论】:

    【解决方案2】:

    【讨论】:

    • 像往常一样,常见问题解答提供了不好的建议。使用指针意味着对象不会始终被破坏,关于破坏顺序问题的后续观点是完全错误的:stackoverflow.com/questions/335369/…
    • @LokiAstari:很有趣。这是完全错误的吗?常见问题解答提到“如果 a、b 和 c 的构造函数使用 ans,您通常应该没问题,因为运行时系统将在静态反初始化期间,在这三个对象中的最后一个被破坏后破坏 ans。”,尽管我同意它不应该如此轻视它。
    • 他认为泄漏不是问题,因为内存已被操作系统清理。这只是草率和糟糕。任何带有构造函数/析构函数的东西都不是真正的内存;它关于这些对象拥有的资源及其清理。这些对象中可能有任何东西,当你修改一个对象时,你会检查你intentionally leak 的所有地方,以确保泄漏不会影响你的代码正确性(我猜你甚至找不到这些地方)。所以他的评论唯一相关的是没有构造函数/析构函数的东西。
    • (cont...) 但是对于这些对象,您甚至不需要使用这种技术,因为全局变量保证在使用前被初始化:int globaleX = 5;。当没有代码可用于初始化时,您根本不需要这种技术。因此,他是完全错误的。但我离题了。就我个人而言,我发现该网站强调了很多糟糕的技术,并且有一些对于初学者来说并不明显的明显错误,并且作者缺乏纠正或评论这些不良内容的意愿使得该网站不可靠。这也是为什么 SO 更喜欢内部讨论链接而不是外部网站的原因。
    • 作为一个容易找到的例子:你能发现这里有什么问题吗:parashift.com/c++-faq-lite/new/placement-new.html
    【解决方案3】:

    我假设您看到这种行为是因为您在没有显式函数调用的情况下对全局变量进行内联初始化。例如globals.cpp:

     // top of source file
    
     #include "myincludes.h"
    
     CSomeClass someObject(432);
     int global_x = 42;
     int global_y = InitY();
    

    全局对象的构造函数和析构函数的顺序以及全局变量的初始化顺序大多是不确定的。 (在没有参考标准参考页面的情况下,我推测源文件中的变量从顶部声明到底部进行初始化,但没有定义“哪个源文件先出现”的顺序。)

    最好的解决方案是没有任何全局对象(构造函数在库中的任何函数之前运行)或依赖于全局变量初始化顺序。

    最好有一个显式初始化库的函数。也许您需要应用程序在启动时调用此函数,或者您的库的导出函数在检测到初始化未发生后调用它。然后初始化你的全局变量。

    在我的团队中,严格禁止在“main”(或“DllMain”)之前运行的代码。换句话说,没有全局对象。没有用于初始化全局变量的函数。

    【讨论】:

      猜你喜欢
      • 2010-09-29
      • 2014-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多