【发布时间】:2017-02-12 20:08:04
【问题描述】:
我继承了一个应用程序,该应用程序包含一个动态链接到 MFC 的常规 DLL,该应用程序是从一个 Windows 服务可执行文件加载的,该可执行文件也动态链接到 MFC。该代码正在使用 Microsoft Visual Studio 2008 Professional(旧的,我知道...)进行编译。这个应用程序已经“工作”了好几年,但我发现由于 appcore.cpp 中的以下断言,我无法将它作为调试版本运行:
调试断言失败! 程序:C:\Projects\CMM\Debug\CMM.exe 文件:f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\appcore.cpp 线路:380
有关您的程序如何导致断言的更多信息 失败,请参阅有关断言的 Visual C++ 文档。
(按重试调试应用程序)
对应CWinApp构造函数中的如下代码:
ASSERT(AfxGetThread() == NULL);
pThreadState->m_pCurrentWinThread = this;
ASSERT(AfxGetThread() == this);
当通过 LoadLibrary 加载 DLL 时会发生这种情况,这让我怀疑应用程序多年来的工作更多是靠运气而不是判断(由于 ASSERT 未包含在发布版本中)。
我(诚然有限)对 MFC 的理解是,虽然通常应该只有一个 CWinApp 实例,但在常规 DLL 中可以有一个额外的实例,它动态链接到 MFC,就像在这种情况下一样。该代码在服务可执行文件中有一个实例,在 DLL 中有一个实例。 CWinApp 构造函数被调用 3 次 (?),一次用于 MFC 框架内的某个内部实例,一次用于服务可执行文件中的实例,一次用于 DLL 中的实例。前两个工作正常,第三个爆炸了。
所有导出的函数都以AFX_MANAGE_STATE 开头(尽管执行永远不会那么远)并且我相信预处理器标志是正确的 w.r.t。 Microsoft 的文档(_AFXDLL 用于 EXE,_AFXDLL、_USRDLL 和 _WINDLL 用于 DLL)。
我尝试使用AfxLoadLibrary 代替LoadLibrary 无效。但是,如果我包括
AFX_MANAGE_STATE( AfxGetStaticModuleState() )
在调用LoadLibrary/AfxLoadLibrary 的函数开始时,CWinApp 对象已实际构造,但随后在 dllmodul.cpp 中执行失败。
谁能解释为什么会发生这种情况或我需要做些什么来解决它?
编辑
这是断言发生时的调用堆栈:
mfc90d.dll!CWinApp::CWinApp(const char * lpszAppName=0x00000000) Line 380 + 0x1c bytes C++
cimdll.dll!CCimDllApp::CCimDllApp() Line 146 + 0x19 bytes C++
cimdll.dll!`dynamic initializer for 'theApp''() Line 129 + 0xd bytes C++
msvcr90d.dll!_initterm(void (void)* * pfbegin=0x1b887c88, void (void)* * pfend=0x1b887d6c) Line 903 C
cimdll.dll!_CRT_INIT(void * hDllHandle=0x1b770000, unsigned long dwReason=1, void * lpreserved=0x00000000) Line 318 + 0xf bytes C
cimdll.dll!__DllMainCRTStartup(void * hDllHandle=0x1b770000, unsigned long dwReason=1, void * lpreserved=0x00000000) Line 540 + 0x11 bytes C
cimdll.dll!_DllMainCRTStartup(void * hDllHandle=0x1b770000, unsigned long dwReason=1, void * lpreserved=0x00000000) Line 510 + 0x11 bytes C
ntdll.dll!_LdrxCallInitRoutine@16() + 0x16 bytes
ntdll.dll!LdrpCallInitRoutine() + 0x43 bytes
ntdll.dll!LdrpInitializeNode() + 0x101 bytes
ntdll.dll!LdrpInitializeGraphRecurse() + 0x71 bytes
ntdll.dll!LdrpPrepareModuleForExecution() + 0x8b bytes
ntdll.dll!LdrpLoadDllInternal() + 0x121 bytes
ntdll.dll!LdrpLoadDll() + 0x92 bytes
ntdll.dll!_LdrLoadDll@16() + 0xd9 bytes
KernelBase.dll!_LoadLibraryExW@12() + 0x138 bytes
KernelBase.dll!_LoadLibraryExA@12() + 0x26 bytes
KernelBase.dll!_LoadLibraryA@4() + 0x32 bytes
mfc90d.dll!AfxCtxLoadLibraryA(const char * lpLibFileName=0x02a70ce0) Line 487 + 0x74 bytes C++
mfc90d.dll!AfxLoadLibrary(const char * lpszModuleName=0x02a70ce0) Line 193 + 0x9 bytes C++
CMM.exe!CMonDevDll::LoadDLL() Line 207 + 0x1b bytes C++
CMM.exe!CMonDevDll::LoadDllEntryPoints() Line 268 + 0x8 bytes C++
CMM.exe!CMonDevDll::Initialize(CMonDevRun * pMonDevRun=0x0019fe60) Line 186 + 0x8 bytes C++
CMM.exe!CCtcLinkMonDev::Initialize(CMonDevRun * pMonDevRun=0x0019fe60, CCtcRegistry & reg={...}, int nLinkId=1) Line 546 + 0x18 bytes C++
CMM.exe!CCtcLinkSwitchMgr::Initialize(CMonDevRun * pMonDevRun=0x0019fe60, CCtcRegistry & reg={...}) Line 188 + 0x14 bytes C++
CMM.exe!CMonDevRun::Initialize(ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char> > > szServiceName="CimService") Line 257 + 0x16 bytes C++
CMM.exe!CMonDevService::Run() Line 202 + 0x2d bytes C++
CommonFilesD.dll!CCtcServiceBase::ParseStandardArgs(int argc=-1, char * * argv=0x02a51b44) Line 278 + 0xf bytes C++
CMM.exe!main(int argc=4, char * * argv=0x02a51b38) Line 126 + 0x16 bytes C++
CMM.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C
CMM.exe!mainCRTStartup() Line 403 C
kernel32.dll!@BaseThreadInitThunk@12() + 0x24 bytes
ntdll.dll!__RtlUserThreadStart() + 0x2f bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
【问题讨论】:
-
你能告诉我应用程序是类成员还是外部成员。
-
@SantoshDhanawade,
theApp被声明为全局变量,它不是类成员,也没有外部引用。 -
嗨@SantoshDhanawade,感谢您的链接。我实际上在发帖之前阅读了第一个,但它确实描述了我面临的问题。不幸的是,我没有从任何构造函数加载 DLL,也没有发现可执行文件和 DLL 之间链接参数的库版本中存在任何不匹配。第二个提到了
AFX_MANAGE_STATE宏,但是我导出的函数已经使用了它,并且无论如何执行都不会那么远。无论如何感谢您的帮助。
标签: visual-c++ dll mfc