Sch*_*ght 0 c++ visual-c++ visual-studio-2017
我正在尝试将一个项目从 VS2013 升级到 VS2017。除了一件事之外,我一切都在工作 - 调用 printf 时遇到了崩溃。崩溃是这样的:
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++
Run Code Online (Sandbox Code Playgroud)
该行如下所示:
printf("simple string goes here");
Run Code Online (Sandbox Code Playgroud)
我已经将崩溃追踪到以下几行:
freopen("/dev/null", "a", stdout);
freopen("/dev/null", "a", stderr);
Run Code Online (Sandbox Code Playgroud)
我可以通过用这个替换这些行来修复它:
freopen("nul", "a", stdout);
freopen("nul", "a", stderr);
Run Code Online (Sandbox Code Playgroud)
对于那些可能比我更了解内部机制的人,我有三个问题:
编辑
似乎没有可移植的方法来做到这一点,所以我只是使用了旧的平台特定代码。
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);
Run Code Online (Sandbox Code Playgroud)
这是 Windows 和 Unix 存在不可调和的差异的地方之一,你只需要处理。我会这样做:
#ifdef _WIN32
#define NULL_DEVICE "NUL:"
#else
#define NULL_DEVICE "/dev/null"
#endif
Run Code Online (Sandbox Code Playgroud)
进而
freopen(NULL_DEVICE, "w", stdout);
Run Code Online (Sandbox Code Playgroud)
在 Windows 的情况下,在 NUL 后面放一个冒号可以防止他们在未来的 Windows 版本中决定不希望在每个目录中都有魔法名称的可能性。
我不知道为什么"/dev/null"在 VS2013 中工作 - 根据我所知道的一切,它不应该有。