调试断言失败

3
当我在调试模式下运行程序时,遇到了“Debug assertions failed!”错误。我尝试在Visual C++网站上查找此错误,但解释对我来说太高级,并且与我猜测的问题没有任何相似之处。
我已经检查了代码并缩小了错误发生的位置。似乎是在手动删除一堆堆栈数组并在计算机移动到程序的下一部分时发生。当我注释掉释放旧堆栈数组的部分时,程序运行得很好。
我的编程知识还比较基础,你有什么想法?
谢谢。
我在使用Visual C++ 2008。
更多信息:
断点触发在以下代码块:
 void operator delete(
    void *pUserData
    )
{
    _CrtMemBlockHeader * pHead;

    RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));

    if (pUserData == NULL)
        return;

    _mlock(_HEAP_LOCK);  /* block other threads */
    __TRY

        /* get a pointer to memory block header */
        pHead = pHdr(pUserData);

         /* verify block type */
        _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));//<---- break point triggers 

        _free_dbg( pUserData, pHead->nBlockUse );

    __FINALLY
        _munlock(_HEAP_LOCK);  /* release other threads */
    __END_TRY_FINALLY

    return;
}

这段代码来自标签:dbgdel.cpp 我已经“缩小范围”并确定引起问题的代码段如下:
delete [] topQuadanglesPositions;
delete [] fourClamps;
delete [] precaculatedClamp1;
delete [] precaculatedClamp2;
delete [] precaculatedClamp3;
delete [] precaculatedClamp4;
delete [] area;
delete [] hullConfiguration;
delete [] output;
delete [] prunedListClamp1;
delete [] prunedListClamp2;
delete [] prunedListClamp3;
delete [] prunedListClamp4;
delete [] numValidLocations;

如果我注释掉这一段,程序就可以正常运行。

如果你已经缩小了问题范围,请发布你的代码!我们无法读懂你的思维,帮助我们帮助你。 - Sam Miller
3
@Faken - 有争议。重新审视您的新建/删除用法并进行替换可能比调试当前代码更快。这也使得后续的维护工作更容易。从您的数据中可以看出,您似乎没有破坏当前代码的风险,因为它正在破坏堆栈。 - Steve Townsend
1
@Faken 对的。当你到那里时,打开Debug-> Window-> Callstack(或类似的东西),然后双击列表中出现的项以查看程序如何到达这段代码。 - Yakov Galka
1
@Faken:你的代码已经出了问题,如果让它更清晰、更好,你还能失去什么呢?(而且天哪,那是太多的删除了。) - GManNickG
1
但是,既然您选择承担管理自己内存的不必要负担,那么您的程序已经由new/delete等操作包裹着业务逻辑。去掉这些操作,只留下逻辑,之后您的生活将会变得更加轻松。特别是如果您正在学习。现在是养成良好习惯的时候。 - Steve Townsend
显示剩余7条评论
3个回答

7
您的代码正在破坏堆。第一个代码片段来自C运行时库,assert指示您的程序将错误的指针值传递给delete运算符。
注释掉delete语句只是隐藏了问题。随着程序的不断开发,它会以不同的方式回来困扰您。在此线程中有一些调试提示。学习如何捕获这些类型的错误是任何C或C++程序员必须经历的仪式。欢迎加入我们的组。

谢谢您的简单解释!我会查看那个线程,看看能否从中获得任何关于正在发生的事情的想法。 - Faken
感谢您的建议,我找到了问题所在。我将两个指针链接到同一个数组,并尝试删除这两个指针所指向的数据,第一次删除是可以的,但第二次删除时就会产生错误。 - Faken
2
那很快。恭喜。 - Hans Passant

2

断言是只有在调试模式下才会被执行的语句(廉价的调试检查)。

例如,以下代码会在调试模式下失败断言,但在发布模式下不会导致错误:

ASSERT(1 == 2);

很可能你调用的某个方法需要特定的输入参数,但是没有得到它。这不会立即导致错误(因此您的代码在非调试模式下工作)。希望这有所帮助。如果您能发布具体的代码,其他人就可以为您提供更具体的响应。

1

断言是指程序进入非法状态时发生的情况。程序员在代码中编写断言,以便在出现问题时通知他。您必须从IDE开始调试,并在收到断言消息时按下中断。然后,您应该查看断言中的条件,例如assert(i > 1024),并确保它永远不会成为真。也许您对断言的含义有一些评论,您必须找到发生断言的行以及原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接