Windows DLL&动态初始化排序

时间:2014-07-19 02:32:35

标签: windows dll posix dylib shared-libraries

对于Windows和POSIX,我有一些关于动态初始化(即main之前的构造函数)和DLL链接排序的问题。

为了便于讨论,我将定义几个术语:

  

加载时间库:已经过链接的库#34;在编译   时间,当系统加载我的应用程序时,它们会被加载   在自动。 (即放在CMake的target_link_libraries中的那些   命令)。

     

运行时库:我通过dlopen或手动加载的库   等价物。出于本次讨论的目的,我只说我   在main中使用dlopen手动加载库,所以这应该   简化事情。

     

动态初始化:如果您不熟悉C ++规范   对此的定义,请不要试图回答这个问题。

好的,我们假设我有一个应用程序(MyAwesomeApp),它链接到动态库(MyLib1),而动态库又链接到另一个库(MyLib2)。所以依赖树是:

MyAwesomeApp - > MyLib1 - > MyLib2

对于这个例子,让我们说MyLib1和MyLib2都是Load-Time Libraries。

上面的初始化顺序是什么?显而易见的是,所有静态初始化(包括导出/导入函数的链接(仅限窗口))都将首先发生......但动态初始化会发生什么?我期待整体订购:

所有导入/导出符号链接
所有静态初始化
所有MyLib2的动态初始化
所有MyLib1的动态初始化
所有MyAwesomeApp的动态初始化
MyAwesomeApp的main()函数

但是我无法找到任何要求这样做的规格。我看到了暗示它的小精灵的东西,但我需要在规格中找到保证,让我做一些我想做的事情。

为了确保我的想法清楚,我希望图书馆加载的工作方式非常类似于在Python中导入,如果它还没有加载,那么它就会被加载。我会在做任何事情之前完全加载(包括任何初始化)......如果它已被加载,那么我只是链接到它。

提供一个更复杂的示例,以确保我的第一个示例的另一个定义产生不同的响应:

MyAwesomeApp依赖于MyLib1& MyLib2 MyLib1依赖于MyLib2

我希望进行以下初始化:

所有导入/导出符号链接
所有静态初始化
所有MyLib2的动态初始化
所有MyLib1的动态初始化
所有MyAwesomeApp的动态初始化
MyAwesomeApp的main()函数

我喜欢任何帮助,指出说它是这样的规格。或者,如果这是错误的,任何说明真正发生的规范!

提前致谢!

-Christopher

1 个答案:

答案 0 :(得分:3)

C ++标准中没有任何内容要求动态链接如何工作。

话虽如此,Visual Studio附带了C Runtime(又名CRT)源,您可以在dllcrt0.c中看到静态初始化器的运行位置。

如果您考虑运行每个阶段需要满足哪些约束,您还可以推导出操作的相对顺序:

  1. 导入/导出解析只需要.dll。
  2. 静态初始化只需要.dll。
  3. 动态初始化需要为.dll解析所有导入。
  4. 第1步& 2不要相互依赖,所以它们可以独立发生。步骤3需要1&每个.dll都有2个,所以它必须在1和1之后发生。 2。

    因此,满足上述约束的任何特定加载顺序都是有效的加载顺序。

    换句话说,如果您需要关心特定步骤的特定顺序,那么您可能正在做一些危险的事情,这些事情依赖于在OS的主要或次要修订版本中不会保留的实现特定细节。例如,加载程序锁对.dll的工作方式在各种版本的Windows中发生了显着变化。