有关SetThreadErrorMode(),SetErrorMode(),_ set_error_mode()和_CrtSetReportMode()

时间:2018-12-23 22:39:03

标签: c++ c windows winapi

我有一个用C ++编写并使用Visual Studio 2015编译的命令行应用程序。

我需要确保在自动,无人值守的功能测试期间,特别是在断言失败(来自assert()的标准<cassert>的情况下),该应用程序不会被错误对话框阻止。

我最初认为https://stackoverflow.com/a/6925695/393756中建议的以下调用可以完成此任务,但没有成功

_set_error_mode(_OUT_TO_STDERR);

通过实验,我最终发现,以下代码至少在失败的断言对话框方面达到了预期的效果,

SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);

_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);

_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);

_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);

问题:

  1. _set_error_mode(_OUT_TO_STDERR)为什么不够用?如果我正确理解documentation,就应该知道。

  2. 为什么_CrtSetReportMode(_CRT_ASSERT)(加上相关的_CrtSetReportFile()调用)不足以禁用对话断言?显然,我还需要配置_CRT_ERROR

  3. 为了确保没有打开任何对话框,我应该打电话给SetErrorMode(),如果可以的话用什么参数呢?

  4. 我应该选择SetThreadErrorMode()吗?

2 个答案:

答案 0 :(得分:1)

_set_error_mode配置assert_CrtSetReportMode配置_CrtDbgReport,它仅在CRT的调试版本中定义,并通过_ASSERTE之类的宏在内部使用。

虽然_set_error_mode足以从assert禁用消息框,但这还不够,因为assert调用了abort。在调试版本中,abort的默认行为包括_WRITE_ABORT_MSG,它报告运行时错误,并调用_CrtDbgReportW来报告_CRT_ERROR。您可以通过_set_abort_behavior _CrtSetReportMode更改中止行为,而无需(0, _WRITE_ABORT_MSG)来避免这种情况。但是,鉴于您的目标是禁止在调试版本中显示所有消息框,因此对于CRT内部使用_CrtSetReportMode和调用_ASSERTE的相关宏,您仍然需要_CrtDbgReport

要配置Windows错误报告,请在进程启动时调用SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)。如果子进程应使用默认错误模式而不是继承此模式,请在CREATE_DEFAULT_ERROR_MODE调用中使用CreateProcess创建标志。

答案 1 :(得分:-1)

assert()宏不会直接在VS中生成异常。选中this。您调用的函数会在发生异常时尝试阻止消息框(在这种情况下,您可以安装顶级exception handler)。

因此,您不能停止它,因为它是一个简单的MessageBox(),它在调用abort()之前。创建此宏是为了在调试模式下显示编程错误,如果您不希望显示任何内容,则可以使用自己的assert()函数,不包括assert.h。