移植到 VS2015/.NET 4.6 后,C++/CLI DLL 在加载时崩溃

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

老实说,这可能是 VS2015: Migrated project compiles, but won't run ("Debug Assertion Failed!") 的骗局,但没有答案,我有更多详细信息。

最近将我们的代码库从针对 v4.0 的 VS2010 移植到针对 v4.6 的 VS2015。我们有一个托管的 C++ DLL 来提供对我们的 C++ 代码库的 .NET 访问。所有引用它的 .NET 应用程序在启动时崩溃。似乎在退出时崩溃注册静态销毁。

调试调用栈如下:

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] 

发布调用堆栈看起来大致相同:

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] 

您是否可能混淆了调试和发布代码? ucrtbased.dll 是调试通用 CRT DLL。 Windows 为调试和发布维护不同的堆,混合使用它们肯定会导致此类错误。不同的 C 运行时 DLL(例如 VS2010、2012、2015)也维护不同的堆。在一个堆上分配内存并在另一个堆上取消分配也会导致这些类型的错误。

例如参见http://www.qtcentre.org/threads/29475-HEAP-VariousTests-exe-Invalid-Address-specified-to-RtlValidateHeap

我遇到了完全相同的问题。至少在我的情况下,问题是链接器开关中 "Additional Options" 中的 /NOENTRY 开关。当在链接器设置中选择 "All Options" 时,这 可见。删除 /NOENTRY 也解决了这个问题。

我原来的 (2013) 项目文件确实有这个开关;然而,2013 年的版本确实有效。因此,要么该开关在 2013 年被忽略,要么整个链接过程发生了变化。 (从外观上看,我认为它有很多。)