François Beaune
François Beaune

Reputation: 4500

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

I have a command line application written in C++ and compiled with Visual Studio 2015.

I need to make sure this application doesn't get blocked by error dialogs during automatic, unattended functional testing, in particular in the case of failing assertions (standard assert() from <cassert>).

I initially thought that the following call suggested in https://stackoverflow.com/a/6925695/393756 would do the job, but it didn't:

_set_error_mode(_OUT_TO_STDERR);

By experimenting I eventually found out that the following code achieves the intended effect, at least when it comes to failing assertion dialogs:

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);

Questions:

  1. Why isn't _set_error_mode(_OUT_TO_STDERR) sufficient? If I understand the documentation correctly, it should.

  2. Why isn't _CrtSetReportMode(_CRT_ASSERT) (plus the associated _CrtSetReportFile() call) sufficient to disable dialogs for assertions? Apparently I need to also configure _CRT_ERROR.

  3. In order to make sure that no dialog is ever opened, should I call SetErrorMode(), and if so with what arguments?

  4. Should I prefer SetThreadErrorMode()?

Upvotes: 5

Views: 1169

Answers (2)

Michael Chourdakis
Michael Chourdakis

Reputation: 11178

The assert() macro does not generate an exception directly in VS. Check this. The functions you are calling try to block message boxes when an exception occurs (in which case you can install a top level exception handler).

Therefore, you cannot stop it because it is a simple MessageBox() before it calls abort(). This macro is created to show programming errors in debug mode, if you do not want anything to be displayed, you can use your own assert() function, not including assert.h.

Upvotes: -1

Eryk Sun
Eryk Sun

Reputation: 34270

_set_error_mode configures assert. _CrtSetReportMode configures _CrtDbgReport, which is only defined in the debug build of the CRT and used by it internally via macros such as _ASSERTE.

While it would seem _set_error_mode should suffice to disable message boxes from assert, it's not enough since assert calls abort. In a debug build, the default behavior of abort includes _WRITE_ABORT_MSG, which reports a runtime error, which calls _CrtDbgReportW to report a _CRT_ERROR. You can avoid this without _CrtSetReportMode by changing the abort behavior via _set_abort_behavior(0, _WRITE_ABORT_MSG). But given your objective is to suppress all message boxes in the debug build, you'll still need _CrtSetReportMode for the CRT's internal use of _ASSERTE and related macros that call _CrtDbgReport.

To configure Windows error reporting, call SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX) at process startup. If a child process should use the default error mode instead of inheriting this mode, use the CREATE_DEFAULT_ERROR_MODE creation flag in CreateProcess calls.

Upvotes: 5

Related Questions