题
我有一个 .cpp
文件(让我们叫它 statinit.cpp
)编制并链接到我可执行的使用 gcc
.我 main()
功能 不 在 statinit.cpp
.
statinit.cpp
有一些静态的初始化,我需要运行。然而,我从来没有明确参考任何东西从 statinit.cpp
我 main()
, ,或在任何引用。会发生什么情况(I假设)是联系对象的创造了 statinit.cpp
是从来不装载在运行时,让我静初始化从来没有运行,引起的问题在其他地方的代码(这是调试非常困难的,但是我跟踪它最终).
是否有一个标准图书馆功能、连接器的选择,编译器的选择,或者东西可以让我的力量,对象为负荷运行时间而不引用其中一个元素?
什么我想要做的是确定一个虚拟的功能statinit.cpp宣布这一标题的文件 main()
看,这叫伪功能 main()
.然而,这是一个非常丑陋的解决方案我非常想要避免的变化statinit.cpp 本身。
谢谢, 丹尼尔
解决方案
它是不完全清楚问题是什么:
C++不具有该概念的初始化时的静态.
因此,一个想你有一个对象中的"文件的范围"。
- 如果这个目的是在全球命名空间,那么它将是建造之前,主要()称为和破坏之后,主要()退出(假设它是在应用程序)。
- 如果这个对象是在一个名字空间然后选择地执行可以选择懒惰的初始化的变量。这只是意味着它将以充分的前初始化第一次使用。所以如果你依赖的侧影响从建设然后把目在全球的名字空间。
现在一个理由你不可能看到的构造这一目执行的是,它不接入的应用程序。这是一个接头的问题并不是一个语言问题。这种情况发生时,对象是汇编成一个静态的图书馆和应用程序,然后联系对静态的图书馆。连接将只载入应用程序的功能/目的是明确引用该应用程序(即事情解决不确定的事情中的符号表格)。
为了解决这个问题,你有几种选择。
- 不用静态的图书馆。
- 编译成的动态图书馆(该准则如今).
- 汇编的所有源直接进入应用程序。
- 做一个明确的参考目内主要的。
其他提示
我遇到同样的问题。
写文件,DoNotOptimizeAway.cpp
:
void NoDeadcodeElimination()
{
// Here use at least once each of the variables that you'll need.
}
然后,从NoDeadcodeElimination()
调用main
。
修改:另外,您可以编辑您的连接选项,并告诉它始终链接的一切,即使不是使用它。我不喜欢这种方式,因为虽然可执行文件会得到更大的。
这些问题,并与这些潜在的解决方案的问题回避的事实都围绕你不能保证许多关于静态初始化。所以,因为它不是可靠的,不依赖于它!
显式使用静态“InititalizeLibrary”类型的静态功能初始化数据。现在,你能保证它发生,并根据你当你拨打电话的保证时,它相对于其他代码发生。
一个C ++“肥胖型的方式来做到这一点是与单例。
基本上,写一个函数以返回到对象的引用。迫使它进行初始化,使它在函数内部中的静态对象。
请一类的静态函数,依稀这样的:
class MyClass {
static MyClass& getObject()
{
static MyObject obj;
return obj;
}
};
由于您使用C ++,你总是可以声明一个全局对象(即一个全局变量,它引用statinit.cpp
一个类。像往常一样,构造函数将被调用的初始化和由于对象是全球性的,这将被称为前main()的运行。
有是虽然一个非常重要的警告。谁也不能保证何时构造函数将被调用,没有办法每一个构造函数被调用时明确下令。这也可能会击败任何试图检查内存泄漏,因为你不再能保证在运行主已释放所有的内存分配。
时的问题,静态项目是的从不的初始化,或者是问题,当你需要使用它们的静态项目未初始化?
所有静态初始化应该在你的主要完蛋()运行。不过,如果你初始化静态物体与另一静态对象,你可以遇到的问题。 (注意:如果使用的是原语,如int这并不适用)
例如,如果有在x.cpp文件:
static myClass x(someVals);
和在y.cpp的:
static myClass y = x * 2;
这是可能的,该系统将尝试实例y被生成的X之前。在这种情况下,“y”的变量将可能是0,因为x是可能0被初始化之前。
在一般情况下,这种情况的最佳解决方案是实例化对象时,它第一次使用(如果可能)。不过,我注意到你上面是不允许修改该文件。从该文件中的值被用于其他地方,也许你可以改变这些值是如何被访问的?
阅读ld命令的手册页,并期待在-u选项。如果statinit.cpp定义任何看起来像一个函数,那么尝试-u命名。否则,选择在statinit.cpp和名称定义在-u的数据对象,并希望它的作品。我认为这是最好的,如果你写的命令行,以便-u选项已statinit的目标代码在它为个人媒体库-l选项之前,立即来了。
当然动态库解决方案是最好的,但我也被告知有可能整个静态库与链接器选项链接:
-Wl,-whole-archive
库的-l
选项之前,和
-Wl,-no-whole-archive
后(以避免包括其他库作为一个整体,太)。