【问题标题】:Windows CRT and assert reporting (abort,retry,ignore)Windows CRT 和断言报告(中止、重试、忽略)
【发布时间】:2009-07-13 19:55:20
【问题描述】:

如果应用程序遇到assert(false) 并且有时它会被创建多次并填满我的屏幕,那么处于调试模式的 Windows CRT 将显示一个“Abort,Retry, Ignore”窗口。

如果断言会在调试器中中断并且不问我任何问题,我会很高兴。

我修改了CRT reporting flags,没有效果。

我也尝试过修改reporting hook。它确实会在出现 25-30 个“中止”对话框后被调用。

如果有帮助,我正在构建一个由单独的程序加载的 DLL。看起来加载我的 DLL 的主机程序与调用我的代码的线程不一致。 似乎其中一个线程已停止,但其他线程仍在运行。

如何配置 CRT 来执行此操作?

【问题讨论】:

    标签: visual-studio visual-studio-2008 visual-c++


    【解决方案1】:

    这有效(至少对我而言,在 2008 年): (本质上,从钩子函数返回 TRUE)

    int __cdecl CrtDbgHook(int nReportType, char* szMsg, int* pnRet)
    {
        return TRUE;//Return true - Abort,Retry,Ignore dialog will *not* be displayed
        return FALSE;//Return false - Abort,Retry,Ignore dialog *will be displayed*
    }
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, CrtDbgHook);
        assert(false);
        getch();
        return 1;
    }
    

    您也可以编写自己的类似断言的行为(请注意,这将显示“中断,继续”对话框):

    #define MYASSERT(x) { if(!(x)) {DbgRaiseAssertionFailure();} }
    
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        MYASSERT(false);
        getch();
        return 1;
    }
    

    希望有帮助!

    【讨论】:

    • 不幸的是,这并不能解决我的问题。在调用 CrtDbgHook 之前,我得到了大约 25-30 个 Abort、Retry、Ignore 对话框。
    【解决方案2】:

    廖的回答带你走了大部分路,但我想建议你在调试钩子中再添加一件事:

    int __cdecl StraightToDebugger(int, char*, int*)
    {
      _CrtDbgBreak(); // breaks into debugger
      return TRUE; // handled -- don't process further.
    }
    

    否则,您的断言将消失,过程将终止。

    这种方法的问题是 - 至少对于我的 VC Express 家庭安装来说 - 调试器会抛出一个大的“program.exe 已触发断点”消息,而不是正常的断言失败,所以它可能不是很大的进步。

    【讨论】:

      【解决方案3】:

      我不确定您是否希望该行为适用于任何assert,或者您是否只是想将assert(false) 专门用作通用模式以无条件地进入给定行上的调试器。如果是前者,请参阅 Liao 和 Kim 的答案。如果是后者,那么你真的应该改用__debugbreak 内在函数。

      【讨论】:

      • assert 要求中断并仅在调试版本中触发,而__debugbreak 无论如何都会中断?
      • __debugbreak 从字面上看是在您的代码中放置一个断点指令(例如 x86 上的 INT 3) - 因此它会在任何构建中中断,并且不会显示带有文本等的漂亮消息框。
      【解决方案4】:

      为什么要断言? assert(false) 看起来像“不应该发生”的代码在 CRT 中执行。如果我是你,我会害怕。它总是在一条线上吗?周围有cmets吗?

      编辑: 我的意思是:断言发生在 CRT 代码中,因为有一些假设它正在检查你不满足(也许你设法链接到混合运行时,或者你制作托管 C++ 程序集并忘记手动初始化 CRT,或者你试图调用来自 DllMain 的 LoadLibrary,或其他不应该发生的事情)。

      所以在弄清楚如何抑制断言之前,首先要弄清楚它为什么会断言。否则,您以后可能会遇到看似无关的问题,并且尝试调试它们会很有趣。 (根据您的问题,不清楚您是否知道这些断言是关于什么的)

      这样的代码

      if(somebadcondition)
      {
          assert(false);
          // recovery code
      }
      

      字面意思是“这个代码分支永远不应该被执行”。

      【讨论】:

      • 你的意思是为什么 assert(false) 断言?这是因为当您断言时,条件应评估为 true 为“ok”,即“断言 a+b=4”,因此如果 a+b 不等于 4,则“断言失败”。
      • 抱歉,我无法理解您的最后两个问题 - 什么总是在一条线上?任何“围绕”它的 cmets - 你是什么意思?
      • 您是绝对正确的,首先应该弄清楚断言发生的原因。并使用断言(假);当然是确保“永远不应执行此代码分支”的一种方法。 +1 用于为此添加更多信息/正确做法,这是我忽略的。
      【解决方案5】:

      为什么不使用DebugBreak Function

      或者甚至使用操作码?

      #ifdef _X86_
      #define BreakPoint()        _asm { int 3h }
      #else
      #define BreakPoint()        DebugBreak()
      #endif
      

      Before Visual C++ 2005, the instruction,

      __asm int 3 编译时没有导致生成本机代码 /clr;编译器翻译了 CLR 中断指令 操作说明。从 Visual C++ 开始 2005 年,__asm int 3 现在导致 本机代码生成 功能。如果你想要一个函数 在您的代码中造成断点,并且 如果您希望将该函数编译为 MSIL,使用 __debugbreak。

      【讨论】:

      • 我不想更改断言宏的定义。这不仅适用于我的代码,也适用于我链接的静态库,也使用断言宏
      猜你喜欢
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 2023-03-06
      • 2018-04-12
      相关资源
      最近更新 更多