2012-09-13 32 views
0

我正在使用覆盖C运行时库中的内存管理函数的第三方API。为了使所有内容正常工作,我必须在任何内存分配发生之前进行调用以初始化API。在静态成员分配之前调用函数

我的工作,该项目采用任何在主文件中的代码被执行之前被动态初始化静态工厂对象。

如何确保在静态Factory对象之前初始化API?

+1

你不能保证全球静在初始化的顺序。函数的局部静态初始化在使用前,所以常常全球静态可放入'实例()'函数,然后你可以控制的顺序他们被称为。 – BoBTFish

+0

@BoBTFish工厂对象是一个类的静态成员。这会改变什么吗? – Derek

+0

就初始化顺序而言,它不会改变任何内容。 – piokuc

回答

5

C++标准库遇到同样的问题:它必须确保cin,cout等在任何代码(包括静态对象的构造函数)使用它们之前被初始化。为处理这种情况而发明的技巧也可以解决你的问题。在被包含在每一个翻译单元第一一个头文件(当然,这与动态初始化静态对象的每一个翻译单元):

class init_library { 
public: 
    init_library() { if (counter++ == 0) initilaize_the_library(); } 
private: 
    static int counter; 
}; 

static init_library i_library; 

,并在一个翻译单元,你必须提供init_library::counter定义。

这将使init_library类型的静态对象中,在头想尽一切办法翻译单元。 ,并在第一时间,这些对象之一被初始化,它会调用 - 它的初始化将在同一翻译单元其他初始化(!不要忘了,因为它的#include指令来第一)之前发生初始化库的代码。 (请注意,此代码是不是线程安全的,使线程安全的是直接的)

这被称为“漂亮的反招”。

+0

你说得对。在Visual Studio中,_initterm会初始化与标准库关联的静态成员。我认为静态分配是可以的,但是动态分配会让API变得更糟。 – Derek

+1

酷,+1,但正如你所说,它不是线程安全的。我正在研究一个在基于AIX的超级计算机上运行的库,并且在系统+ IBM编译器+库的最后一次升级之后,事实证明MPI在初始化我的C++库(和main之前)时产生了线程,所以我的全局静态工厂正在崩溃。所以我将所有这些静态全局工厂移动到客户端代码在使用我的lib之前调用的函数。问题解决了。 – piokuc

+1

@Derek - 是的,有编译器特定的钩子来控制初始化和清理。这就是为什么我说“发明的技巧”,而不是“使用的技巧”,“”。 –

5

你应该将你的静态工厂对象动初始化静态函数调用该函数初始化第三方的lib作为一个主后第一件事情。

+0

真的那么简单吗?没有什么内部正在初始化我可以告诉的Factory对象。 – Derek

+0

如果您希望程序始终按预期运行,则这是必要的。谷歌和阅读有关静态对象初始化失败。 – piokuc

+2

@Derek,静态对象通过在main之前运行的隐藏代码初始化,除非它们是函数本地的,并且您无法控制它们初始化的顺序。代码块本地的静态代码在执行代码块之前不会被初始化。 –

相关问题