如何初始化堆,以便常规 MFC dll 中的静态构造函数可以使用它?
Posted
技术标签:
【中文标题】如何初始化堆,以便常规 MFC dll 中的静态构造函数可以使用它?【英文标题】:How to initialize the heap so it can be used by static constructors in a regular MFC dll? 【发布时间】:2017-05-25 16:48:26 【问题描述】:背景:我有一个带有 MFC UI 的大型遗留 C++ 应用程序。我正在尝试重构项目并将其迁移到新的 .Net UI。现在,作为第一步,我正在尝试将 Visual Studio 2015 中的 MFC exe 项目重构为可以从 exe 项目中调用的常规 MFC dll。 (见下文)我们计划逐渐将 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
这是我在构造函数断点时的调用堆栈
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++。
【问题讨论】:
您的整个项目是否使用相同的运行时支持版本和内存模型? 什么是静态构造函数? 在解决方案项目属性中,所有项目(静态库、dll和exe项目)都使用“多线程调试DLL(/MDd)” dll设置为“在a中使用MFC共享 DLL" “静态构造函数”也许我说错了。静态对象的构造函数,在某些情况下需要做复杂的事情并访问堆,就是问题所在。所以 SomeData fileLevelStatic;在应用程序代码之前调用构造函数 SomeData::SomeData() 【参考方案1】:事实证明,遗留代码已在本地覆盖 ::operator new() 并且它正在做一些复杂的事情,现在已经被破坏了。这特别令人困惑,因为我在行上有一个断点 char* mem = new char[10];
并且 F11 直到我在 new() 函数中实际放置了一个断点之前,才进入 new 的本地实现。
所以基本上是自制的脚枪...... 叹。谢谢您的帮助。
【讨论】:
【参考方案2】:在加载 dll 期间调用构造函数。也许到那时堆还没有为 dll 初始化。
初始化代码的正确位置是 InitInstance 和 ExitInstance 或 DllMain,您也可以在其中进行清理。将你的构造函数和析构函数代码移到那里。
【讨论】:
以上是关于如何初始化堆,以便常规 MFC dll 中的静态构造函数可以使用它?的主要内容,如果未能解决你的问题,请参考以下文章