如何初始化堆,以便常规MFC dll中的静态构造函数可以使用它?

时间:2017-05-25 16:48:26

标签: c++ visual-c++ dll mfc

背景:我有一个带有MFC UI的大型遗留C ++应用程序。我正在尝试重构项目并将其迁移到新的.Net用户界面。现在作为第一步,我试图将Visual Studio 2015中的MFC exe项目重构为一个常规的MFC dll,我可以从exe项目中调用它。 (见下文)我们计划逐步将UI从MFC移动到.Net。我们正试图在飞机降落时改变发动机......

无论如何,我在遗留C ++应用程序中遇到各种静态和全局变量问题。当我将新的DLL加载到exe中时,我得到一个带有访问冲突的异常。原来在dll中没有正确创建堆,我不明白为什么......

我将问题缩小到一个带有文件级静态变量的非常简单的结构。该变量在正常应用程序逻辑之前调用库加载时的构造函数。

在MfcDll项目的SomeData.cpp中

struct SomeData {
    SomeData()
    {
        ::OutputDebugString("construct data\n");
        char* mem = new char[10]; // nope
        if (mem)
        {
            ::OutputDebugString("got mem\n");
        }
        else
        {
            ::OutputDebugString("no heap\n");
        }
    }
};

SomeData fileLevelStatic;

输出结果为:

construct data
no heap

当我断开构造函数

时,这是我的callstack
MfcDll.dll!SomeData::SomeData() Line 57 C++
MfcDll.dll!`dynamic initializer for 'fileLevelStatic''() Line 63    C++
ucrtbased.dll!00007ffdc88f947d()    Unknown
MfcDll.dll!dllmain_crt_process_attach(HINSTANCE__ * const instance, void * const reserved) Line 67  C++
MfcDll.dll!dllmain_crt_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 133   C++
MfcDll.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 190   C++
MfcDll.dll!_DllMainCRTStartup(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 249 C++
ntdll.dll!00007ffe005da35f()    Unknown

那我在这里做错了什么?我需要做什么来确保我有一个可用于静态对象的堆。遗留应用程序广泛使用静态和全局变量。是的,我们想重构那些但是它是一项艰巨的任务,所以我们需要在我们这样做时保持它的工作......

另外要验证它不是.Net与MFC的关系,我在仅使用C ++的解决方案中进行此特定测试。我有MFCDll,遗留的静态链接C ++库和库存窗口应用程序项目也在C ++中引用MFCDll。所以.Net在这一点上甚至不在代码中......它是所有带有MFC和Windows的C ++。

2 个答案:

答案 0 :(得分:1)

事实证明遗留代码已经在本地覆盖了:: operator new(),并且它正在做一些复杂的事情,现在已经破坏了。这特别令人困惑,因为我在线上有一个断点 char * mem = new char [10];

和F11没有进入new的本地实现,直到我在new()函数中实际设置了一个断点。

所以基本上是家用脚枪...... 叹。谢谢您的帮助。

答案 1 :(得分:0)

在dll的加载时间内调用构造函数。也许到那时候堆还没有为dll初始化。

初始化代码的正确位置是InitInstance和ExitInstance或DllMain,您也可以在其中进行清理。将构造函数和析构函数代码移到那里。