C#中的堆错误

Posted

技术标签:

【中文标题】C#中的堆错误【英文标题】:Heap error in C# 【发布时间】:2012-07-03 15:07:58 【问题描述】:

我有一个 C# 程序来测试 C++/CLI 程序集(此程序集是原生 C++ dll 的包装器),我收到以下错误消息:

Unhandled exception at 0x50f8fd85 (msvcr90d.dll) in TestKeyManagerApp.exe: 0xC0000005:     Access violation writing location 0x00000000.

调试模式的最后位置:dbgheap.c(Visual Studio 2008 输出)

if (pHead == NULL)

    *errno_tmp = ENOMEM; <----- ACCESS VIOLATION
    RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));

我创建了一次程序集类的对象(我的 C# 程序的私有成员),在构造函数中我加载了本机 C++ dll,现在如果我第二次使用程序集对象(第二次调用测试函数)我得到了这个错误消息!

调用栈的输出:

msvcr90d.dll!_heap_alloc_dbg_impl(unsigned int nSize=532, int nBlockUse=2, const char * szFileName=0x50ec24a8, int nLine=588, int * errno_tmp=0x00000000)  Line 431 + 0x3 bytes C++

msvcr90d.dll!_nh_malloc_dbg_impl(unsigned int nSize=532, int nhFlag=0, int nBlockUse=2, const char * szFileName=0x50ec24a8, int nLine=588, int * errno_tmp=0x00000000)  Line 239 + 0x19 bytes   C++

msvcr90d.dll!_calloc_dbg_impl(unsigned int nNum=1, unsigned int nSize=532, int nBlockUse=2, const char * szFileName=0x50ec24a8, int nLine=588, int * errno_tmp=0x00000000)  Line 593 + 0x20 bytes   C++

msvcr90d.dll!_getptd_noexit()  Line 588 + 0x1a bytes    C

msvcr90d.dll!_errno()  Line 281 + 0x5 bytes C

msvcr90d.dll!_calloc_dbg(unsigned int nNum=1, unsigned int nSize=532, int nBlockUse=2, const char * szFileName=0x50ec20a4, int nLine=373)  Line 646 + 0x11 bytes    C++

msvcr90d.dll!__CRTDLL_INIT(void * hDllHandle=0x50ec0000, unsigned long dwReason=2, void * lpreserved=0x00000000)  Line 373 + 0x18 bytes C

msvcr90d.dll!_CRTDLL_INIT(void * hDllHandle=0x50ec0000, unsigned long dwReason=2, void * lpreserved=0x00000000)  Line 214 + 0x11 bytes  C

ntdll.dll!77c68968()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!77c73820()    
ntdll.dll!77c735bc()    

希望你能给我一些提示或提示?

谢谢!

【问题讨论】:

你能发布更多代码吗?看起来您正在访问一些未初始化的变量。 显然errno_tmp 也是NULL。它来自哪里? @leon22 你能展示你的DllImport 部分吗? @Desolator C++/CLI 中没有 P/Invoke 【参考方案1】:

检查调用堆栈,特别是非托管堆栈。为此,您必须启用非托管代码调试。 这可能是虚假的删除或危险/无效的指针访问。通过最小化本机 DLL 调用来缩小问题范围。

【讨论】:

【参考方案2】:

错误的可能原因:

指针 errno_tmp 可能指向已删除的内存,或指向数组边界之外(-ve 索引或索引 >= 长度)。

使用了无效的P\Invoke,或者加载的程序集已经是free

【讨论】:

errno_tmp 是 CRT 内部的,如果它是 0x00,则可能之前有什么东西损坏了内存。在 C++/CLI 中,您无需 P/Invoke 本机代码,只需调用它。

以上是关于C#中的堆错误的主要内容,如果未能解决你的问题,请参考以下文章

詹金斯中的堆空间错误

C++分段错误中的堆算法

混合模式 C++/CLI 崩溃:atexit 中的堆损坏(静态析构函数注册)

Jenkins 中的堆空间问题

sparklyr中的堆空间不足,但有足够的内存

非托管 C++ 代码向托管代码发送字符串的错误