C++/CLI DLL crashes on load after port to VS2015 /

2019-07-12 16:53发布

问题:

Honestly, this is may be a dupe of VS2015: Migrated project compiles, but won't run ("Debug Assertion Failed!") but that has no answer and I have more details.

Recently ported our codebase from VS2010 targeting v4.0 to VS2015 targeting v4.6. We have a managed C++ DLL to provide .NET access to our C++ codebase. All .NET applications which reference it crash on startup. It seems to be crashing registering statics for destruction at exit.

Here is the debug callstack:

ntdll.dll!RtlValidateHeap() Unknown
KernelBase.dll!_HeapValidate@12()   Unknown
ucrtbased.dll!_CrtIsValidHeapPointer(const void * block) Line 1385  C++
ucrtbased.dll!_msize_dbg(void * block, int block_use) Line 1037 C++
ucrtbased.dll!_msize(void * block) Line 30  C++
ucrtbased.dll!_recalloc_dbg(void * block, unsigned int count, unsigned int element_size, int block_use, const char * file_name, int line_number) Line 771   C++
ucrtbased.dll!_register_onexit_function::__l23::<lambda>() Line 112 C++
ucrtbased.dll!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) &,void <lambda>(void) >(__acrt_lock_and_call::__l3::void <lambda>(void) && setup, _register_onexit_function::__l23::int <lambda>(void) & action, __acrt_lock_and_call::__l4::void <lambda>(void) && cleanup) Line 199  C++
ucrtbased.dll!__acrt_lock_and_call<int <lambda>(void) >(const __acrt_lock_id lock_id, _register_onexit_function::__l23::int <lambda>(void) && action) Line 882  C++
ucrtbased.dll!_register_onexit_function(_onexit_table_t * table, int (void) * function) Line 148    C++
zwrappers.dll!_onexit(int (void) * function) Line 268   C++
zwrappers.dll!atexit(void (void) * function) Line 276   C++
zwrappers.dll!__scrt_initialize_thread_safe_statics() Line 107  C++
[External Code] 
clrjit.dll!Compiler::impResolveToken(unsigned char const *,struct CORINFO_RESOLVED_TOKEN *,enum CorInfoTokenKind)   Unknown
clrjit.dll!Compiler::impImportBlockCode(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImportBlock(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImport(struct BasicBlock *) Unknown
clrjit.dll!Compiler::compCompile(void * *,unsigned long *,unsigned int) Unknown
clrjit.dll!Compiler::compCompileHelper(struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,enum CorInfoInstantiationVerification)    Unknown
clrjit.dll!Compiler::compCompile(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int)    Unknown
clrjit.dll!jitNativeCode(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,void *) Unknown
clrjit.dll!CILJit::compileMethod(class ICorJitInfo *,struct CORINFO_METHOD_INFO *,unsigned int,unsigned char * *,unsigned long *)   Unknown
[External Code] 
clrjit.dll!Compiler::impResolveToken(unsigned char const *,struct CORINFO_RESOLVED_TOKEN *,enum CorInfoTokenKind)   Unknown
clrjit.dll!Compiler::impImportBlockCode(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImportBlock(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImport(struct BasicBlock *) Unknown
clrjit.dll!Compiler::compCompile(void * *,unsigned long *,unsigned int) Unknown
clrjit.dll!Compiler::compCompileHelper(struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,enum CorInfoInstantiationVerification)    Unknown
clrjit.dll!Compiler::compCompile(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int)    Unknown
clrjit.dll!jitNativeCode(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,void *) Unknown
clrjit.dll!CILJit::compileMethod(class ICorJitInfo *,struct CORINFO_METHOD_INFO *,unsigned int,unsigned char * *,unsigned long *)   Unknown
[External Code] 
user32.dll!__InternalCallWinProc@20()   Unknown
user32.dll!UserCallWinProcCheckWow()    Unknown
user32.dll!DispatchMessageWorker()  Unknown
user32.dll!_DispatchMessageW@4()    Unknown
WindowsBase.ni.dll!53fee59c()   Unknown
[Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack]   
[External Code] 

The release callstack looks about identical:

ntdll.dll!_RtlReportCriticalFailure@8() Unknown
ntdll.dll!_RtlpHeapHandleError@4()  Unknown
ntdll.dll!_RtlpLogHeapFailure@24()  Unknown
ntdll.dll!RtlSizeHeap() Unknown
ucrtbase.dll!_register_onexit_function()    Unknown
zwrappers.dll!_onexit(int (void) * function) Line 268   C++
zwrappers.dll!atexit(void (void) * function) Line 276   C++
zwrappers.dll!__scrt_initialize_thread_safe_statics() Line 107  C++
[External Code] 
clrjit.dll!Compiler::impResolveToken(unsigned char const *,struct CORINFO_RESOLVED_TOKEN *,enum CorInfoTokenKind)   Unknown
clrjit.dll!Compiler::impImportBlockCode(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImportBlock(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImport(struct BasicBlock *) Unknown
clrjit.dll!Compiler::compCompile(void * *,unsigned long *,unsigned int) Unknown
clrjit.dll!Compiler::compCompileHelper(struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,enum CorInfoInstantiationVerification)    Unknown
clrjit.dll!Compiler::compCompile(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int)    Unknown
clrjit.dll!jitNativeCode(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,void *) Unknown
clrjit.dll!CILJit::compileMethod(class ICorJitInfo *,struct CORINFO_METHOD_INFO *,unsigned int,unsigned char * *,unsigned long *)   Unknown
[External Code] 
clrjit.dll!Compiler::impResolveToken(unsigned char const *,struct CORINFO_RESOLVED_TOKEN *,enum CorInfoTokenKind)   Unknown
clrjit.dll!Compiler::impImportBlockCode(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImportBlock(struct BasicBlock *)    Unknown
clrjit.dll!Compiler::impImport(struct BasicBlock *) Unknown
clrjit.dll!Compiler::compCompile(void * *,unsigned long *,unsigned int) Unknown
clrjit.dll!Compiler::compCompileHelper(struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,enum CorInfoInstantiationVerification)    Unknown
clrjit.dll!Compiler::compCompile(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int)    Unknown
clrjit.dll!jitNativeCode(struct CORINFO_METHOD_STRUCT_ *,struct CORINFO_MODULE_STRUCT_ *,class ICorJitInfo *,struct CORINFO_METHOD_INFO *,void * *,unsigned long *,unsigned int,void *) Unknown
clrjit.dll!CILJit::compileMethod(class ICorJitInfo *,struct CORINFO_METHOD_INFO *,unsigned int,unsigned char * *,unsigned long *)   Unknown
[External Code] 
user32.dll!__InternalCallWinProc@20()   Unknown
user32.dll!UserCallWinProcCheckWow()    Unknown
user32.dll!DispatchMessageWorker()  Unknown
user32.dll!_DispatchMessageW@4()    Unknown
WindowsBase.ni.dll!53fee59c()   Unknown
[Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack]   
[External Code] 

回答1:

I had the exact same problem. At least in my case, the problem was the /NOENTRY switch in "Additional Options" in the linker switches. This is only visible when "All Options" is selected in the linker settings. Removing /NOENTRY also removed the problem.

My original (2013) project file did have this switch; however, the 2013 build did work. So either that switch was ignored in 2013, or the whole linking process has changed. (which from the looks i assume it has quite a bit.)



回答2:

Is it possible that you are mixing up debug and release code? ucrtbased.dll is the debug universal CRT DLL. Windows maintains different heaps for debug versus release and mixing them can definitely cause errors like these. The different C runtime DLL's (e.g., VS2010, 2012, 2015) also maintain different heaps. Allocating memory on one heap and deallocating on another will cause these types of errors too.

See http://www.qtcentre.org/threads/29475-HEAP-VariousTests-exe-Invalid-Address-specified-to-RtlValidateHeap for example.