为什么在 Visual Studio 2010 中使用 MFC 作为 DLL 的 MFC SDI 程序中使用我的 DLL 时会发生泄漏?
这可能更好地针对 Microsoft 支持,但想知道是否有人对为什么会发生这种情况有任何想法。
我创建了一个简单的 C++ DLL,如下所示:
//simpledll.h
class simpledll {
public:
__declspec(dllexport) simpledll();
__declspec(dllexport) ~simpledll();
}
//someheader.h
#include <string>
const std::string SomeString(L"I'm Leaking");
//simpledll.cpp
#include "simpledll.h"
#include "someheader.h"
//some code to generate memory leak debug messages
simpledll::simpledll(){ /*code to register for memory leak debug messages*/}
simpledll::~simpledll(){}
接下来,我使用 VS 2010 中的默认设置创建一个通用的 MFC SDI(单文档接口)应用程序。在 MainFrm.h 中,我 #include“simpledll.h” 并创建一个成员变量: simpledll mSimpleDLL;
这就是有趣的地方。如果我同时编译面向 v100 的 DLL 和 MFC 应用程序(均使用 /MDd 开关),则只需启动然后关闭应用程序就会产生内存泄漏。如果我将 MFC 应用程序中的“使用 MFC”设置更改为在静态库中使用 MFC,则泄漏就会消失。然后,如果我重新编译针对 v90 的 DLL 并使用 MFC 的 DLL 版本重新编译 MFC 应用程序,则不会出现内存泄漏。将 DLL 切换为使用 v100,将 MFC 应用程序切换为使用 v90,并且没有内存泄漏。事实上,似乎会产生内存泄漏的唯一组合是当 DLL 和 MFC 应用程序都以 v100 为目标并且 MFC 应用程序使用 MFC 作为共享 DLL 时。我什至在 VS11 开发者预览版中尝试过此操作,当目标为 v110 时,一切正常。
有人遇到过这个问题吗?它仅限于 VS2010 中的 SDI MFC 应用程序吗?是什么原因导致这些泄漏?我假设它与调用 SomeString 常量的析构函数之前终止 DLL 有关,但为什么使用 MFC 作为 DLL 会影响这一点呢?
This may be better directed to Microsoft support, but was wondering if anyone had any ideas as to why this is happening.
I created a simple C++ DLL like the following:
//simpledll.h
class simpledll {
public:
__declspec(dllexport) simpledll();
__declspec(dllexport) ~simpledll();
}
//someheader.h
#include <string>
const std::string SomeString(L"I'm Leaking");
//simpledll.cpp
#include "simpledll.h"
#include "someheader.h"
//some code to generate memory leak debug messages
simpledll::simpledll(){ /*code to register for memory leak debug messages*/}
simpledll::~simpledll(){}
Next, I make a generic MFC SDI (single document interface) application using the default settings in VS 2010. In MainFrm.h I #include "simpledll.h" and create a member variable: simpledll mSimpleDLL;
Here's where it gets interesting. If I compile both the DLL and the MFC application targeting v100 (both using the /MDd switch), simply starting and then closing the application generates a memory leak. If I change the "Use of MFC" setting in the MFC app to use MFC in a static library, the leak goes away. Then, if I recompile the DLL targeting v90 and recompile the MFC app using the DLL version of MFC, no memory leak. Switch the DLL to use v100 and the MFC app to use v90 and no memory leak. In fact, the only combination that seems to generate a memory leak is when both the DLL and the MFC app target v100 and the MFC app is using MFC as a shared DLL. I even tried this with the VS11 developer preview and when targeting v110, everything worked fine.
Has anyone run into this issue? Is it limited just to the SDI MFC app in VS2010? What could be causing these leaks? I'm assuming it has something to do with the DLL being terminated prior to calling the destructor of the SomeString constant, but why would using MFC as a DLL affect that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我相信这只是 SomeString 初始化顺序与 AfxEnableMemoryTracking() 调用顺序的问题(如果我没记错的话)。事实上,内存泄漏可能发生在其他版本中,但 SomeString 可能在内存泄漏跟踪激活之前就已被分配,或者在检查发生之前已被释放(不太可能,样本中没有明确的内容)。
您可以尝试通过为 SomeString 分配一个新值来使另一个构建显示泄漏,并使用更长的字符串来确保完成新的内存分配。从 simpledll 的构造函数中执行此操作。但首先,您必须将字符串声明移动到 simpledll.cpp 文件中,否则您将在每个包含 someHeader.h 的 .cpp 中获得一个新实例。
编辑:它不是 MFC 特有的,任何 DLL 都会发生这种情况,但由于 MFC 自动启用内存泄漏检测,它在 MFC 应用程序中变得更加明显。
I believe it is simply a question of in which order SomeString is initialized versus the call to AfxEnableMemoryTracking() (if I remember correctly). In fact, the memory leak probably happen in the other builds, but SomeString may have been allocated before the memory leak tracking was activated, or it was released before the check happens (unlikely, nothing clear it in the sample).
You can try to make the other build to show the leak by assigning a new value to SomeString, with a longuer string to be sure a new memory allocation is done. Do it from the simpledll's constructor. But first, you have to move the string declaration inside simpledll.cpp file, otherwize you get a new instance into each .cpp that include someHeader.h.
Edit: It is not specific to MFC, that would happens with any DLL, but as MFC automatically enable the memory leak detection, it become more visible in MFC applications.
两年半后...
我将一个不使用 MFC 的重要独立应用程序转换为旨在由 MFC 程序加载的非 MFC DLL。一切正常,但 VS 2010 调试器报告无休止的内存泄漏。
线索是这些内存泄漏是在调用 DLL 清理函数之前在退出时报告的。
这里有一个同样详细和复杂的解决方案的详细讨论:
http:// /www.vis-sim.com/3dsceneBB/viewtopic.php?t=1027
涉及指定 MFC 库依赖项。然而,还有一个更简单的解决方案:
可以在此处找到编程替代方案(以及延迟加载 DLL 优点和缺点的讨论):
http://www.codeproject.com/Articles/9428/Delay-Loading-a-DLL
这里的好处是延迟加载的DLL在MFC之前卸载DLL 被卸载,因此 MFC 不再报告错误的内存泄漏。
请注意,这只需要对 DLL 的调试版本执行此操作,以抑制错误的内存泄漏消息。在RELEASE版本中DLL仍然可以静态链接,从而避免了延迟链接DLL的缺点。
Two-and-one-half years later ...
I converted a non-trivial standalone application that did not use MFC to a non-MFC DLL that was intended to be loaded by an MFC program. Everything worked, but the VS 2010 debugger reported endless memory leaks.
The clue was that these memory leaks were being reported on exit before the DLL cleanup functions were being called.
There is a detailed discussion with an equally detailed and complex solution here:
http://www.vis-sim.com/3dsceneBB/viewtopic.php?t=1027
that involves specifying MFC library dependencies. There is however a much simpler solution:
A programmatic alternative (along with a discussion of delay-loaded DLL advantages and disadvantages) can be found here:
http://www.codeproject.com/Articles/9428/Delay-Loading-a-DLL
The advantage here is that the delay-loaded DLL is unloaded before the MFC DLL is unloaded, and so MFC no longer reports false memory leaks.
NOTE that this only needs to be done for the DEBUG version your DLL in order to suppress the false memory leak messages. The DLL can still be statically linked in the RELEASE version, thereby avoiding the disadvantages of delay-linked DLLs.