我编写了一个DLL,DLL中导出来了一个类,类里面定义了一个vector以及map,然后用exe去调用DLL,当DLL的运行时库使用MTD时,vs2010就不会报内存泄漏;DLL的运行时库使用MDD时,vs2010就会出现内存泄漏;另外,很奇怪的是,当DLL的运行时库使用MDD,exe调用DLL时,连接加载对应的DLL的lib,采用在代码中#pragma comment(lib,"../Debug/MemoryLeakDemo.lib")形式时,vs就不会提示内存泄漏,而在vs工程中的配置选项中连接的形式,就会提示出现内存泄漏;
DLL中的代码:
IncludeInc.h
#pragma once
#ifdef MEMORYLEAKDEMO_EXPORTS
#define MEMORYLEAKDEMO_EXPORTS _declspec(dllexport)
#else
#define MEMORYLEAKDEMO_EXPORTS _declspec(dllimport)
#endif
#include "ITestDemo.h"
MEMORYLEAKDEMO_EXPORTS ITestDemo* OPenSkinRes();
IncludeInc.cpp的代码:
#include "IncludeInc.h"
#include "TestDemo.h"
MEMORYLEAKDEMO_EXPORTS ITestDemo* OPenSkinRes(){
ITestDemo* pTemp = CTestDemo::GetInstance();
return pTemp;
}
ITestDemo.h代码
#pragma once
class ITestDemo{
public:
virtual int GetUI() = 0;
};
TestDemo.h中代码
#include "ITestDemo.h"
#include
#include
class CTestDemo :public ITestDemo
{
public:
static CTestDemo* GetInstance(){
static CTestDemo g_res;
return &g_res;
}
virtual int GetUI();
private:
CTestDemo(void);
~CTestDemo(void);
public:
static int s_sDemo1;
static std::string s_strDemo2;
private:
std::vector m_vecDynamic;
std::vector m_vecTest;
};
TestDemo.cpp代码:
#include "StdAfx.h"
#include "TestDemo.h"
int CTestDemo::s_sDemo1 =0;
std::string CTestDemo::s_strDemo2 = "Test";
CTestDemo::CTestDemo(void)
{
for (int i = 0; i < 100 ; i++)
{
m_vecDynamic.push_back(new int(i));
}
}
CTestDemo::~CTestDemo(void)
{
std::vector::iterator it = m_vecDynamic.begin();
for (; it != m_vecDynamic.end(); ++it)
{
int * pTemp = *it;
delete pTemp;
}
}
int CTestDemo::GetUI(){
return 1;
}
exe中的代码:
// CallMemoryLeak.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "CallMemoryLeak.h"
#include "CallMemoryLeakDlg.h"
#include "../MemoryLeakDemo/IncludeInc.h"
#include "../MemoryLeakDemo/ITestDemo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//#pragma comment(lib,"../Debug/MemoryLeakDemo.lib")
// CCallMemoryLeakApp
BEGIN_MESSAGE_MAP(CCallMemoryLeakApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CCallMemoryLeakApp construction
CCallMemoryLeakApp::CCallMemoryLeakApp()
{
// support Restart Manager
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CCallMemoryLeakApp object
CCallMemoryLeakApp theApp;
// CCallMemoryLeakApp initialization
BOOL CCallMemoryLeakApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
// Create the shell manager, in case the dialog contains
// any shell tree view or shell list view controls.
CShellManager *pShellManager = new CShellManager;
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
//就这两行调用代码,其他的都是MFC默认生成的
ITestDemo* pTeset = OPenSkinRes();
int iRet = pTeset->GetUI();
CCallMemoryLeakDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Delete the shell manager created above.
if (pShellManager != NULL)
{
delete pShellManager;
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}