【发布时间】:2012-10-17 11:30:46
【问题描述】:
拥有一个隐式加载某些 DLL 和显式加载其他 DLL 的 EXE(LoadLibrary)。这个 EXE 正在执行它的 ExitProcess(剩下的进程中的 1 个线程),并且作为忙于卸载 DLL 的一部分,比如 A.DLL。
A.DLL(不幸的是)有一个静态的。调用 atexit 回调并开始调用此静态的析构函数,留下一系列析构函数,直到析构函数决定进行一些清理并加载 DLL 来执行此操作。此 DLL 执行某些方法,直到由于内存访问冲突而发生崩溃,因为它将在此 DLL 中使用的静态不再存在。查看此静态的堆栈跟踪,它的析构函数已作为其 DLL 卸载的一部分被调用。
发生了什么? DLL 被加载,执行了一些方法,去使用一个静态的(在同一个 DLL 中),但是这个已经被破坏了(静态只在 dll 被卸载时被破坏)。那么它是否处于执行方法的半不确定状态但也正在被破坏?
EXE 似乎在 __tmainCRTStartup 的上下文中,这意味着用户创建的 main 已返回? DLL 是否在用户 main 或 tmainCRTStartup 的上下文中被卸载?
【问题讨论】:
-
在 .exe 的全局析构函数完成后,DLL 在
tmainCRTStartup中被关闭。 -
显式调用 FreeLibrary() 的代码可能会很痛苦,拆除正在运行的程序是一项危险的工作。如果您无法从代码所有者那里获得帮助,则可以调用 exit(0)。请注意 C++11 的 std::quick_exit() 函数,解决了同样的问题。
-
没有 FreeLibrary 调用,运行时正在卸载 dll 的...
-
如果进程在 __tmainCRTStartup 的上下文中,那么我相信该进程还没有开始卸载 DLL(这发生在 __tmainCRTStartup 将控制权返回给 Windows 之后)。听起来好像问题与 DLL 的卸载无关,而与处理 atexit 回调的运行时库有关(正如 ElektroKraut 解释的那样)。如果是这样,使用 ExitProcess 而不是退出 main 函数应该可以解决问题 - 前提是您并不真的 需要 调用任何析构函数。当然,这取决于他们在做什么。
标签: c++ windows visual-c++ dll static