gpt4 book ai didi

DLL 中的 C++ 静态对象没有调用析构函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:54:19 26 4
gpt4 key购买 nike

我遇到 DLL 中的静态析构函数未被调用的问题。正在调用构造函数,但没有调用析构函数。我的 DLL 中有这样一个类

struct DLLDestructorTest
{
int blah;
DLLDestructorTest()
{
blah = 2;
}
~DLLDestructorTest()
{
blah = 0;
}
};
DLLDestructorTest DLLDestructorTestObj;

我可以在构造函数和析构函数中放置断点,我可以验证构造函数断点被命中而析构函数断点没有被命中。如果我在 main.cpp 文件中放入一段类似的代码,我可以验证构造函数和析构函数都将被调用。

调用构造函数时的调用栈如下。

mydll.dll!mydll::DLLDestructorTest::DLLDestructorTest()  Line 1093  C++
mydll.dll!mydll::`dynamic initializer for 'DLLDestructorTestObj''() Line 1100 + 0x26 bytes C++
msvcr90d.dll!_initterm(void (void)* * pfbegin=0x000007fee7f521a8, void (void)* * pfend=0x000007fee7f52bf8) Line 903 C
mydll.dll!_CRT_INIT(void * hDllHandle=0x000007fee7920000, unsigned long dwReason=1, void * lpreserved=0x00000000002cf580) Line 323 C
mydll.dll!__DllMainCRTStartup(void * hDllHandle=0x000007fee7920000, unsigned long dwReason=1, void * lpreserved=0x00000000002cf580) Line 540 + 0x13 bytes C
mydll.dll!_DllMainCRTStartup(void * hDllHandle=0x000007fee7920000, unsigned long dwReason=1, void * lpreserved=0x00000000002cf580) Line 511 C

基本上就是这个网页描述的http://msdn.microsoft.com/en-us/library/988ye33t.aspx This page详细介绍了如何调用构造函数,但没有详细说明如何调用析构函数。在下面的段落中,它提到了有关调用哪些函数来调用构造函数的详细信息,我可以在我的调用堆栈中看到这些信息。

“C/C++ 运行时库代码执行 DLL 启动序列,消除了与 Windows 3.x 中必需的单独模块链接的需要。C/C++ 运行时库代码中包含称为 _DllMainCRTStartup 的 DLL 入口点函数。_DllMainCRTStartup 函数做几件事,包括调用 _CRT_INIT,它初始化 C/C++ 运行时库并在静态、非局部变量上调用 C++ 构造函数。没有这个函数,运行时库将处于未初始化状态。_CRT_INIT 可用于静态链接的 CRT 或从用户 DLL 链接到 CRT DLL Msvcr90.dll。”

我在这里找到了一个帖子 What happens to global variables declared in a DLL? ,但这似乎只是说明将调用析构函数。

任何关于为什么不调用析构函数的想法都将不胜感激。

谢谢,约翰·劳里

更新

我看过这个并阅读了有关 DLL 的内容,但仍然没有解决方案。 DLL 与 __declspec(dllexport) 隐式链接。据我所知,卸载 DLL 不需要做任何特别的事情。它应该在进程终止时自动卸载。

我按照本页 http://msdn.microsoft.com/en-us/library/ms235636(v=vs.90).aspx 上的说明制作了一个非常简单的 DLL .我对从此项目调用析构函数没有任何问题。

我尝试比较这个简单项目和我当前项目之间发生的情况。如果我将断点放在简单的测试项目DLL析构函数中,我可以查看调用堆栈并看到析构函数是从

crtdll.c line 447
crtdll.c line 560
crtdll.c line 510

在我当前的项目中,我可以看到它进入了一个不同的 __DllMainCRTStartup 函数并从第 521 行开始执行。它最终确实到达了第 447 行的同一行,即 (*function_to_call)();但是我的析构函数没有被调用。

如果有用,我调用的 DLL 是来自 juce.com 的 JUCE

谢谢

最佳答案

静态析构函数通常由 C++ 运行时注册以通过 atexit() 函数运行。但它们仅针对应用程序而非 DLL 进行注册。原因是 DLL 可以动态加载和卸载。如果 DLL 注册了 atexit 函数,这些函数指针会在 DLL 卸载时悬空,并会在程序实际退出时导致崩溃。

尽量避免 DLL 中的静态对象。如果你绝对需要它们,那么在库中公开初始化和清理函数,以便用户可以处理它。然后将这些变量转换为指针,并在初始化时新建它们,在 deinit 时删除它们。

关于DLL 中的 C++ 静态对象没有调用析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22500229/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com