代码之家  ›  专栏  ›  技术社区  ›  Community wiki

Windows CRT和断言报告(中止、重试、忽略)

  •  6
  • Community wiki  · 技术社区  · 2 年前

    处于调试模式的Windows CRT将显示 Microsoft Visual C++运行库 与对话 中止、重试、忽略 选项,如果应用程序遇到CRT错误或 assert(false) 有时它被创建多次并填充屏幕。
    此对话框可以包含“调试断言失败”或“调试错误!”之类的行。

    如果断言跳过对话框直接进入调试器,我会很高兴的。

    我修改了 CRT reporting flags 但没有任何效果。
    我还试图修改 reporting hook 。在25-30个“中止”对话框出现后,它确实会被调用。

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

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

    5 回复  |  直到 3 年前
        1
  •  7
  •   Liao    17 年前

    这是有效的(对我来说,至少在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;
    }
    

    希望能有所帮助!

        2
  •  3
  •   Kim Gräsman    17 年前

    廖的回答将带您走完大部分路,但我建议您在调试挂钩中再添加一件事:

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

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

    这种方法的问题是——至少对于我在家安装的VC Express来说——调试器会抛出一个大的“program.exe has triggered a breakpoint”消息,而不是正常的断言失败,所以这可能不是一个很大的改进。

        3
  •  1
  •   Pavel Minaev    17 年前

    我不确定你是否希望这种行为 assert ,或者您是否只是想使用 assert(false) 特别是作为一种通用模式,无条件地闯入给定行上的调试器。如果是前者,请看廖和金的回答。如果是后者,那么您真的应该使用 __debugbreak 而是内在函数。

        4
  •  0
  •   Eugene    17 年前

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

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

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

    代码如下

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

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

        5
  •  0
  •   zproxy    17 年前

    为什么不使用 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。