MFC异常情况

编译异常

情况一:编译DLL程序时,Debug导出函数正确;Release导出的函数不正确如下图所示

Debug

Release

1
?GetApplicationRecoveryParameter@CWinApp@@UAEPAXXZ (public: virtual void * __thiscall CWinApp::GetApplicationRecoveryParameter(void))

原因:编译器优化(Optimization)导致的符号别名(Symbol Aliasing)‌ 问题;‌在开启优化(Release/Optimization On)时,MSVC 编译器发现这个函数的实现极其简单(可能只是直接返回了另一个函数的结果,或者函数体为空/仅包含跳转),于是它执行了“COMDAT 折叠”或“增量链接优化”,将这个函数的导出地址直接指向了它内部调用的那个 MFC 虚函数CWinApp::GetApplicationRecoveryParameter 的地址。

解决方法

方法一:去掉项目的的优化,如下图所示,禁止优化。

方法二:增加“volatile”副作用防止优化

可以在函数内部加入防止优化的代码,迫使编译器保留独立的函数体。

1
2
3
4
5
6
7
8
9
extern "C" __declspec(dllexport) void* xxa()
{
// 防止编译器将其优化为纯别名
volatile int dummy = 0;
dummy++;

return AfxGetApp()->GetApplicationRecoveryParameter();
}

方法三:检查 .def 文件与 __declspec 的冲突

如果你同时使用了 .def 文件和 __declspec(dllexport),在某些优化级别下可能会产生冲突。

建议‌:如果使用 .def 文件导出,请‌移除‌代码中的 __declspec(dllexport),只保留普通的 extern “C” 声明。让链接器完全通过 .def 文件控制导出名称和顺序。

1
extern "C" void* xxa(); // 不要加 __declspec(dllexport)