Visual Studio Windows CRT和Assert报告(中止、重试、忽略)

euoag5mw  于 2023-03-31  发布在  Windows
关注(0)|答案(5)|浏览(146)

如果应用程序遇到CRT错误或assert(false)(有时会创建多次并填满屏幕),处于调试模式的Windows CRT将显示一个带有中止、重试、忽略选项的Microsoft Visual C++运行时库对话框。
此对话框可以包含类似“调试Assert失败”或“调试错误!"这样的行。
我希望Assert能跳过对话框直接进入调试器。
我修改了CRT reporting flags,但没有效果。
我也试过修改reporting hook,它确实在25-30个“中止”对话框出现后被调用。
我正在构建一个由单独的程序加载的DLL,如果这有帮助的话。它看起来也像加载我的DLL的主机程序与调用我的代码的线程不一致。它看起来像一个线程被停止,但其他线程仍在运行。
如何配置CRT来执行此操作?

af7jpaap

af7jpaap1#

这一点很有效(至少对我来说,相对于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;
}

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

#define MYASSERT(x) { if(!(x)) {DbgRaiseAssertionFailure();} }

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    MYASSERT(false);
    getch();
    return 1;
}

希望能有所帮助!

ccgok5k5

ccgok5k52#

Liao的答案基本上可以满足你的要求,但我建议你在调试钩子上再加一个东西:

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

否则,您的Assert将消失,进程将终止。
这种方法的问题是--至少对于我在家里安装的VC Express --调试器抛出一个大的“program.exe已触发断点”消息,而不是正常的Assert失败,所以它可能不是一个很大的改进。

5anewei6

5anewei63#

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

qvtsj1bj

qvtsj1bj4#

为什么要assert?assert(false)看起来像是“should never happen”的代码在CRT中执行。如果我是你,我会害怕。它总是在一行上吗?它周围有注解吗?
我的意思是assert在CRT代码中发生,因为它正在检查一些你不满足的假设(也许你设法链接到混合运行时,或者你制作托管C++汇编而忘记手动初始化CRT,或者你试图从DllMain中调用LoadLibrary,或者其他一些不应该发生的事情)。
因此,在弄清楚如何抑制Assert之前,首先要弄清楚它到底为什么Assert。否则,以后可能会遇到看似无关的问题,并且在调试它们时会有很多乐趣。(从你的问题来看,不清楚你是否知道这些Assert是关于什么的)
像这样的代码

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

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

jvlzgdj9

jvlzgdj95#

为什么不使用DebugBreak Function
或者使用opcode?

#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。

相关问题