调试断言失败:_CrtIsValidHeapPointer(pUserData)

Posted

技术标签:

【中文标题】调试断言失败:_CrtIsValidHeapPointer(pUserData)【英文标题】:Debug Assertion Failed: _CrtIsValidHeapPointer(pUserData) 【发布时间】:2012-05-30 15:36:42 【问题描述】:

有时我在调试模式下运行我的 Qt 项目时遇到“调试断言失败”错误 (image)。 我不知道我错在哪里,因为编译器什么也没说,我不知道该怎么做才能找到我的错误。

我在 Windows Vista 下编程,使用 Qt Creator 2.4.1、Qt 4.8.1。

我的程序必须从激光设备中读取一些信息并将它们保存到一个文件中,其代码类似于:

void runFunction()

    configure_Scanning(...);

    while(...)
    
        // do something
        scanFunction();
        // do something
    

这是我的“有罪”功能(我认为问题出在哪里)

void scanFunction()

    file.open();

    data = getDataFromDevice();

    if(flag)
    
        if(QString::compare(lineB,"")!=0)
        
            QTextStream out(&file);
            out << lineB << endl;
            lineB = "";
        
        lineA.append(data+"\t");
    
    else
    
        if(QString::compare(lineA,"")!=0)
        
            QTextStream out(&file);
            out << lineA << endl;
            lineA = "";
        
        lineB.prepend(data+"\t");
    

    file.close();

lineAlineB 最初是两个 void QString:我的想法是我进行双向扫描以将信息保存在 2D 矩阵中(从 -X 到 +X反之亦然,而 Y 到达指定目标)。 lineA 记住 (-) 到 (+) 的读数; lineB 记住 (+) 到 (-) 的读数。当扫描方向改变时,我将lineA(或lineB)写入文件并继续扫描。

你明白我说的吗? 你能建议我一个解决方案吗?

感谢和抱歉我的英语:P

【问题讨论】:

点击对话框中的重试来调试程序,就像它说的那样。然后检查调用堆栈或将其添加到此问题中,您应该更好地了解出了什么问题。在旁注中,可能不需要不断打开和关闭文件,这会导致一些开销。 我知道在每一步打开和关闭文件并不是最好的策略,但我必须这样做以防止在意外中断的情况下丢失任何数据。 这不是flush() 所做的吗? 如果我将代码 file.open()file.close() 插入到第二个 if 中,在 QTextStream 之前,我只有在确定有内容要写入时才打开文件。我我错了吗?这是防止堆损坏的可能策略吗? 嗯...是的,它可能是(我没想到flush())。但我认为我的问题仍然存在...... 【参考方案1】:

_CrtIsValidHeapPointerUserData 意味着,你有一个堆损坏,这是由调试堆检查器注意到的。怀疑每个可以将任何信息写入任何已删除动态对象的人。 是的,您不会在重写发生时立即收到堆损坏,而是在下一次堆检查时收到堆损坏,这将在任何下一次内存分配/释放时执行。然而,应该由单线程应用程序中的调用堆栈简单地跟踪。

【讨论】:

我没有说“我的”Qt Creator 不允许我使用调试器运行应用程序。所以我无法在运行时检查任何错误。你能解释一下如何检查堆吗? 真的不能说。蛮力方法是用智能指针类替换所有指针,并设置它们在检测到问题时触发错误消息。 好主意!但是......我不知道什么时候检测到问题。无论如何,我会尝试这种方式。感谢您的想法! 最后我找到了如何更改我的调试器(现在我使用 GDB);现在它返回这条消息:HEAP[myApp.exe]: Heap block at 00330BA48 modified at 0330BA78 post requested size of 28;无论如何,我尝试继续,第二条消息是HEAP[myApp.exe]: Invalid address specified to RtlValidateHeap (026F0000, 0330BA50)。你能帮我整理一下这些信息吗? 是的,经典的数组溢出。您在地址 0x0330BA48 有一个数组(或指针),大小为 0x28 字节。然而,一些作家设法在 0x28 字节之后写了一些东西。 0x0330BA78 处的字节被破坏。在我看来,您似乎正在将最后一个字符之后的 '\0' 写入宽(或多字节)字符串。首先检查这些事实。还要检查所有动态数组,尤其是手写的。第二条消息是在检查从 0x026F0000 到 0x0330BA50 的堆块时发现的问题。【参考方案2】:

在我们的例子中,程序在 DEBUG 模式下完美运行,在 RELEASE 模式下崩溃并出现类似的错误跟踪。

在我的例子中,RELEASE 模式在链接器定义中有 msvscrtd.dll。我们将其删除,问题已解决。

或者,将 /NODEFAULTLIB 添加到链接器命令行参数也解决了该问题。

【讨论】:

以上是关于调试断言失败:_CrtIsValidHeapPointer(pUserData)的主要内容,如果未能解决你的问题,请参考以下文章

堆损坏 - 调试断言失败。在 dbgheap.c 第 1322 行表达式 _crtIsValidHeapPointer(pUserData)

调试断言失败_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

调试断言失败表达式:_pFirstBlock == pHead 使用 OpenCV 和 C++ 尝试调用 SurfFeatureDetector

调试断言失败。 BIG_ALLOCATION_ALLIGNMENT

调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

调试断言失败 OpenCv is_block_type_valid(header->_block_use)