我正在尝试将一个项目从 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++
该行看起来像这样:
printf("simple string goes here");
我已将崩溃追踪到这些行:
freopen("/dev/null", "a", stdout);
freopen("/dev/null", "a", stderr);
我可以通过替换以下行来修复它:
freopen("nul", "a", stdout);
freopen("nul", "a", stderr);
我有三个问题要问那些可能比我更了解内部运作的人:
- 这在 VS2013 中有效,但在 VS2017 中崩溃(没有更改操作系统)。这是为什么?
- 当以 Windows 为目标将所有 stdout/stderr 输出重定向为空时,正确的方法是什么,这样 printf 就不会产生可见的输出?
- 是否有安全的跨平台方式来执行此操作?我不一定要寻找插入标准的东西,而是寻找每个主要桌面目标(windows、linux、mac)都可以使用的东西。
编辑
似乎没有可移植的方法来做到这一点,所以我只使用了良好的旧平台特定代码。
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);
最佳答案
这是 Windows 和 Unix 存在不可调和的差异的地方之一,您只需要处理。我会这样做:
#ifdef _WIN32
#define NULL_DEVICE "NUL:"
#else
#define NULL_DEVICE "/dev/null"
#endif
然后
freopen(NULL_DEVICE, "w", stdout);
在 Windows 的情况下,在 NUL 之后放置一个冒号可以防止他们可能在未来的 Windows 版本中决定不希望在每个目录中使用魔法名称。
我不知道为什么 "/dev/null"
在 VS2013 中工作 - 根据我所知道的一切,它不应该。
关于c++ - 将 stdout/stderr 重定向到 null vs2017 c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45391027/