Windows DLL 和动态初始化排序

标签 windows dll posix dylib shared-libraries

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

为了更容易讨论,我将定义几个术语:

Load-Time Libraries: libraries which have been "linked" at compile time such that, when the system loads my application, they get loaded in automatically. (i.e. ones put in CMake's target_link_libraries command).

Run-Time Libraries: libraries which I load manually by dlopen or equivalents. For the purposes of this discussion, I'll say that I only ever manually load libraries using dlopen in main, so this should simplify things.

Dynamic Initialization: if you're not familiar with the C++ spec's definition of this, please don't try to answer this question.

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

MyAwesomeApp -> MyLib1 -> MyLib2

对于此示例,假设 MyLib1 和 MyLib2 都是加载时库。

上面的初始化顺序是什么?显然,所有静态初始化,包括导出/导入函数的链接(仅限 Windows)都会首先发生......但是动态初始化会发生什么?我期望总体排序:

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

但我在规范中找不到任何强制执行此操作的内容。我确实看到 elf 暗示了这一点,但我需要在规范中找到保证,以便我做我想做的事情。

为了确保我的想法清晰,我希望库加载的工作方式与 Python 中的“导入”非常相似,如果尚未加载,它将完全加载(包括任何初始化)在我做任何事情之前...如果它已经加载,那么我将链接到它。

给出一个更复杂的示例,以确保我的第一个示例没有另一个定义会产生不同的响应:

MyAwesomeApp 依赖于 MyLib1 和 MyLib2 MyLib1 依赖于 MyLib2

我期望进行以下初始化:

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

我希望得到任何帮助,指出说明事实如此的规范。或者,如果这是错误的,任何说明真正发生的事情的规范!

提前致谢!

-克里斯托弗

最佳答案

C++ 标准中没有规定动态链接的工作方式。

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

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

  1. 导入/导出解析只需要 .dll。
  2. 静态初始化只需要.dll。
  3. 动态初始化需要解析 .dll 的所有导入。

第 1 步和第 2 步彼此不依赖,因此它们可以独立发生。步骤 3 需要每个 .dll 都有 1 和 2,因此它必须在 1 和 2 之后发生。

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

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

关于Windows DLL 和动态初始化排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24836194/

相关文章:

C++:如何从快捷方式打开 IShellFolder 驱动器文件夹

c++ - 在 Windows 桌面共享 API 上,UAC 提示变为黑色暂停屏幕

python - 使用 CTypes 时检测从 Windows DLL 调用 Python 脚本

c++ - 是否有 posix lstatat 调用之类的东西?

C 和 Linux : Waiting for when a file has been written to

php - 在 Windows 命令行上查找 PHP 版本

windows - 运行.bat文件的命令

mysql - Qt/MySQL 请求在我的计算机上有效,但在其他计算机上无效

java - Cassandra -f 找不到依赖库 java.lang.UnsatisfiedLinkError

concurrency - BSD/Posix插槽可重入吗?