Chris Young
Chris Young

Reputation: 129

Assertion in appcore.cpp while loading regular DLL dynamically linked to MFC

I have inherited an application which consists of a regular DLL which is dynamically linked to MFC and which is loaded from a Windows service executable which also links dynamically to MFC. The code is being compiled using Microsoft Visual Studio 2008 Professional (old, I know...). This application has been 'working' for several years but I have found that I cannot run it as Debug build due to the following assertion in appcore.cpp:

Debug Assertion Failed! Program: C:\Projects\CMM\Debug\CMM.exe File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\appcore.cpp Line: 380

For more information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

which corresponds to the following code in the CWinApp constructor:

ASSERT(AfxGetThread() == NULL);
pThreadState->m_pCurrentWinThread = this;
ASSERT(AfxGetThread() == this);

This occurs when loading the DLL via LoadLibrary and leads me to suspect that the application has worked more by luck than judgement over the years (due to ASSERT not being included as part of the Release build).

My (admittedly limited) understanding of MFC is that although there should generally only be a single instance of CWinApp, it is permissible to have an additional one in regular DLLs which link dynamically to MFC, as in this case. The code has one instance in the service executable and one in the DLL. The CWinApp constructor gets called three (?) times, once for some internal instance within the MFC framework, once for the instance in the service executable and once for the instance in the DLL. The first two work fine, it is the third which blows up.

All of the exported functions start with AFX_MANAGE_STATE (although execution never gets that far) and the pre-processor flags are, I believe, correct w.r.t. Microsoft's documentation (_AFXDLL for the EXE, _AFXDLL, _USRDLL and _WINDLL for the DLL).

I have tried using AfxLoadLibrary instead of LoadLibrary to no effect. However, if I include

AFX_MANAGE_STATE( AfxGetStaticModuleState() )

at the start of the function which calls LoadLibrary/AfxLoadLibrary, the CWinApp object is actually constructed but execution then blows up in dllmodul.cpp instead.

Can anybody shed any light on why this might be happening or what I need to do to fix it?

EDIT

This is the call stack when the assertion occurs:

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    

Upvotes: 2

Views: 2185

Answers (1)

Chris Young
Chris Young

Reputation: 129

I finally managed to track down the cause of my crash. A library used by my DLL was linking statically to Boost.Thread and causing this issue, presumably due to a runtime mismatch. Changing the library to link dynamically to Boost instead seems to have fixed the problem.

Upvotes: 1

Related Questions