I'm trying to upgrade a project from VS2013 to VS2017. I have everything working except for one thing - I'm encountering a crash when printf is called. The crash is as follows:
Unhandled exception at 0x0073910C in exename.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
exename.exe!_invoke_watson(const wchar_t * expression, const wchar_t * function_name, const wchar_t * file_name, unsigned int line_number, unsigned int reserved) Line 224 C++
exename.exe!_invalid_parameter(const wchar_t * const expression, const wchar_t * const function_name, const wchar_t * const file_name, const unsigned int line_number, const unsigned int reserved) Line 112 C++
exename.exe!_invalid_parameter_noinfo() Line 117 C++
exename.exe!_isatty(int fh) Line 17 C++
exename.exe!__acrt_stdio_begin_temporary_buffering_nolock(_iobuf * public_stream) Line 43 C++
[Inline Frame] exename.exe!__acrt_stdio_temporary_buffering_guard::{ctor}(_iobuf * const stream) Line 399 C++
exename.exe!common_vfprintf::__l2::<lambda>() Line 36 C++
exename.exe!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) &,void <lambda>(void) >(__acrt_lock_stream_and_call::__l2::void <lambda>(void) && setup, common_vfprintf::__l2::int <lambda>(void) & action, __acrt_lock_stream_and_call::__l2::void <lambda>(void) && cleanup) Line 204 C++
exename.exe!__acrt_lock_stream_and_call<int <lambda>(void) >(_iobuf * const stream, common_vfprintf::__l2::int <lambda>(void) && action) Line 256 C++
[Inline Frame] exename.exe!common_vfprintf(const unsigned __int64 options, _iobuf * const stream, const char * const format, __crt_locale_pointers * const locale, char * const arglist) Line 34 C++
exename.exe!__stdio_common_vfprintf(unsigned __int64 options, _iobuf * stream, const char * format, __crt_locale_pointers * locale, char * arglist) Line 58 C++
[Inline Frame] exename.exe!_vfprintf_l(_iobuf * const _Stream, const char * const _Format, __crt_locale_pointers * const) Line 638 C++
exename.exe!printf(const char * const _Format, ...) Line 953 C++
The line looks like this:
printf("simple string goes here");
I've tracked the crash down to these lines:
freopen("/dev/null", "a", stdout);
freopen("/dev/null", "a", stderr);
I can fix it by replacing the lines with this:
freopen("nul", "a", stdout);
freopen("nul", "a", stderr);
I have three questions for those who might know the internals at play here better than me:
- This worked in VS2013 but crashes in VS2017 (with no OS change). Why is that?
- What is the correct way when targeting Windows to redirect all stdout/stderr output to nothing, such that printf produces no visible output?
- Is there a safe cross-platform way to do this? I'm not necessarily looking for something inserted into a standard, but rather something that every major desktop target (windows, linux, mac) works with.
EDIT
It seems there's no portable way to do this, so I just went with the good old platform specific code.
const char* nullStream = "/dev/null";
#if defined(WIN32)
nullStream = "nul:";
#endif
// If we fail to redirect either of these streams, we will crash the nex
// time we try to use them. So we assert to be sure.
if (!freopen(nullStream, "a", stdout)) assert(false);
if (!freopen(nullStream, "a", stderr)) assert(false);