简体   繁体   English

在MFC SDI程序中使用MFC作为Visual Studio 2010中的DLL时,为什么我的DLL泄漏?

[英]Why does my DLL leak when using it in an MFC SDI program using MFC as a DLL in Visual Studio 2010?

This may be better directed to Microsoft support, but was wondering if anyone had any ideas as to why this is happening. 这可能更适合Microsoft的支持,但想知道是否有人对此有任何想法。

I created a simple C++ DLL like the following: 我创建了一个简单的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(){}

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; 接下来,我使用VS 2010中的默认设置制作一个通用的MFC SDI(单文档界面)应用程序。在MainFrm.h中,我#include“ simpledll.h”并创建一个成员变量: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. 如果我同时编译DLL和针对v100的MFC应用程序(均使用/ MDd开关),则仅启动然后关闭该应用程序就会产生内存泄漏。 If I change the "Use of MFC" setting in the MFC app to use MFC in a static library, the leak goes away. 如果我将MFC应用程序中的“使用MFC”设置更改为在静态库中使用MFC,则泄漏消失了。 Then, if I recompile the DLL targeting v90 and recompile the MFC app using the DLL version of MFC, no memory leak. 然后,如果我重新编译针对v90的DLL,并使用MFC的DLL版本重新编译MFC应用程序,则不会发生内存泄漏。 Switch the DLL to use v100 and the MFC app to use v90 and no memory leak. 将DLL切换为使用v100,将MFC应用程序切换为使用v90,并且没有内存泄漏。 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. 实际上,似乎产生内存泄漏的唯一组合是当DLL和MFC应用程序目标v100以及MFC应用程序都使用MFC作为共享DLL时。 I even tried this with the VS11 developer preview and when targeting v110, everything worked fine. 我什至在VS11开发人员预览版中进行了尝试,并且在定位到v110时,一切正常。

Has anyone run into this issue? 有没有人遇到这个问题? Is it limited just to the SDI MFC app in VS2010? 它仅限于VS2010中的SDI MFC应用程序吗? 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? 我假设它与DLL在调用SomeString常量的析构函数之前被终止有关,但是为什么将MFC作为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. 我将不使用MFC的非平凡的独立应用程序转换为旨在由MFC程序加载的非MFC DLL。 Everything worked, but the VS 2010 debugger reported endless memory leaks. 一切正常,但是VS 2010调试器报告了无尽的内存泄漏。

The clue was that these memory leaks were being reported on exit before the DLL cleanup functions were being called. 提示是,在调用DLL清除函数之前 ,这些内存泄漏是在退出时报告的。

There is a detailed discussion with an equally detailed and complex solution here: 这里进行了详细的讨论,并提供了同样详细而复杂的解决方案:

http://www.vis-sim.com/3dsceneBB/viewtopic.php?t=1027 http://www.vis-sim.com/3dsceneBB/viewtopic.php?t=1027

that involves specifying MFC library dependencies. 涉及指定MFC库依赖关系。 There is however a much simpler solution: 但是,有一个更简单的解决方案:

  1. In Property Pages->Linker->Input, add your DLL filename to "Delay Loaded DLLs". 在“属性页”->“链接器”->“输入”中,将您的DLL文件名添加到“延迟加载的DLL”中。
  2. In the same dialog box tab, add "delayimp.lib" to "Additional Dependencies". 在同一对话框选项卡中,将“ delayimp.lib”添加到“其他依赖项”。

A programmatic alternative (along with a discussion of delay-loaded DLL advantages and disadvantages) can be found here: 在这里可以找到编程的替代方案(以及对延迟加载的DLL的优缺点的讨论):

http://www.codeproject.com/Articles/9428/Delay-Loading-a-DLL 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. 这样做的好处是延迟加载的DLL在MFC DLL卸载之前就已卸载,因此MFC不再报告错误的内存泄漏。

NOTE that this only needs to be done for the DEBUG version your DLL in order to suppress the false memory leak messages. 注意,只需要对DLL的DEBUG版本执行此操作,以抑制错误的内存泄漏消息。 The DLL can still be statically linked in the RELEASE version, thereby avoiding the disadvantages of delay-linked DLLs. 仍可以在RELEASE版本中静态链接DLL,从而避免了延迟链接DLL的缺点。

Issue still exist in v141 (vs2017). v141(vs2017)中仍然存在问题。

I'm using Delay-loaded DLL as stated above to avoid false memory leak reports. 我如上所述使用延迟加载的DLL,以避免错误的内存泄漏报告。

I believe it is simply a question of in which order SomeString is initialized versus the call to AfxEnableMemoryTracking() (if I remember correctly). 我相信这只是一个简单的问题,即初始化SomeString的顺序与对AfxEnableMemoryTracking()的调用(如果我没记错的话)。 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). 实际上,内存泄漏可能在其他版本中发生,但是SomeString可能是在内存泄漏跟踪被激活之前分配的,或者在检查发生之前被释放的(可能没有清除示例中的内容)。

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. 您可以尝试通过为SomeString分配新值和一个较长的字符串来使另一个版本显示泄漏,以确保完成了新的内存分配。 Do it from the simpledll's constructor. 从simpledll的构造函数执行此操作。 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. 但是首先,您必须将字符串声明移到simpledll.cpp文件中,否则您将在包含someHeader.h的每个.cpp中获得一个新实例。

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的,任何DLL都会发生,但是随着MFC自动启用内存泄漏检测,它在MFC应用程序中变得更加明显。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM