与使用 MFC 的常规 DLL 链接时,MFC 应用程序断言失败
Posted
技术标签:
【中文标题】与使用 MFC 的常规 DLL 链接时,MFC 应用程序断言失败【英文标题】:MFC application Assertion failed when linking with a regular DLL that uses MFC 【发布时间】:2013-06-23 14:24:05 【问题描述】:我正在将旧的 OWL 应用程序迁移到 MFC。有一个包含主要对话框和控件的主库,我开始为旧的 OWL 编写 MFC 的替代类,例如 TDialog[从 CDialogEx 继承]、TEdit .....我现在从 OWL 添加了所有需要的类库构建成功。
我创建了一个新的 MFC 应用程序 [来测试库],我从 dll 中导出了一个函数 [SowDialogue] 以在应用程序中使用,我添加了.lib 的 dll 到 MFC 应用程序,我调用该函数以显示一个简单的对话框,构建成功,但在第一次启动应用程序失败并显示以下消息
我单击重试和中断以获取导致断言的行是那个
所以问题出在资源上。当我与库链接时,MFC 无法获取正确的资源模块。
我认为这是因为我使用了一个使用 MFC 并共享 MFC 对象的常规 dll,如果我必须使用 MFC 扩展库的话。如何将常规库转换为 MFC 扩展库。
或者经过长时间的工作后解决这场灾难的任何方法
编辑
这是调用堆栈,这里没有导出函数,它都在应用程序中,在从 dll 调用任何东西之前出现错误
解决方案
当我将 dll 转换为 MFC 扩展库时,问题得到了解决,实际上我创建了一个新的 mfc 扩展 dll 并欺骗了它的属性、dll 主、stafx 包含和预处理器定义
static AFX_EXTENSION_MODULE MFCExtensionDLL = NULL, NULL ;
extern "C" int APIENTRY DllMain( HINSTANCE hInst, DWORD fdwReason, LPVOID)
if (fdwReason == DLL_PROCESS_ATTACH)
TRACE0("MFCExtension.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(MFCExtensionDLL, hInst))
return 0;
new CDynLinkLibrary(MFCExtensionDLL);
//My initialization code
return 1;
else if (fdwReason == DLL_PROCESS_DETACH)
// Terminate the library before destructors are called
AfxTermExtensionModule(MFCExtensionDLL);
// my finalization code
return 1;
属性
in the properties of project->configuration properties->general Use of MFC = Use MFC in a Shared DLL
,
in the properties of project->configuration properties->C/C++->Preprocessor->Preprocessor Definitions->add _AFXEXT , make sure to delete _USERDLL if it exists
【问题讨论】:
【参考方案1】:在 .dll 中使用 MFC 时,您必须确保 .dll 可以在 .rc 文件中找到诸如字符串和位图之类的资源句柄。 MFC 为每个指向该 .dll 资源的 .dll 维护一个内部状态。当从应用程序(或另一个 .dll)调用该 .dll 时,您必须“帮助”MFC 获取正确的内部状态,否则它将无法找到您的资源并将断言。
在您的示例中,我看不到调用堆栈中的函数正下方的函数,但如果它是导出函数,则可能是 MFC 状态问题。
确保您已将AFX_MANAGE_STATE
宏放在任何可从外部访问的函数(导出函数)的顶部。这将大大有助于解决您的问题。
微软参考:http://msdn.microsoft.com/en-us/library/ba9d5yh5(v=vs.80).aspx
【讨论】:
这里没有调用导出的方法,我添加了调用栈 试着把宏放在OnCreate
的顶部
非常感谢您的努力和帮助,我已经通过将库转换为MFC Extension dll解决了。【参考方案2】:
如果你使用 dll 文件中的资源或窗口,你可以尝试这种方式。此代码可以在 dll 本身中。每当创建资源时,主进程的当前资源句柄都会被设置为dll的资源句柄并使用该句柄。
在任何窗口创建或资源更改后将其恢复为旧值。
hdllresource = ::LoadLibrary(<dllfile containing the resource>);
hcurrentInst = AfxGetResourceHandle();
AfxSetResourceHandle(hdllresource );
//do your window creation or resource loading stuff
AfxSetResourceHandle(hdllresource);
【讨论】:
以上是关于与使用 MFC 的常规 DLL 链接时,MFC 应用程序断言失败的主要内容,如果未能解决你的问题,请参考以下文章