围绕 SetThreadErrorMode()、SetErrorMode()、_set_error_mode() 和 _

Confusion around SetThreadErrorMode(), SetErrorMode(), _set_error_mode() and _CrtSetReportMode()

本文关键字:mode error SetErrorMode SetThreadErrorMode 围绕 set      更新时间:2023-10-16

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

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

我最初认为 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)不够?如果我正确理解文档,它应该。

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

  3. 为了确保没有打开任何对话框,我是否应该调用SetErrorMode(),如果是,用什么参数?

  4. 我应该更喜欢SetThreadErrorMode()吗?

_set_error_mode配置assert._CrtSetReportMode配置_CrtDbgReport,它仅在CRT的调试版本中定义,并由它通过宏(如_ASSERTE)在内部使用。

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

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

assert()宏不会直接在 VS 中生成异常。检查这个。您调用的函数尝试在发生异常时阻止消息框(在这种情况下,您可以安装顶级异常处理程序)。

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

相关文章: