将stdout / stderr重定向到null vs2017 c ++

时间:2017-07-29 15:38:09

标签: 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++

这条线看起来像这样:

printf("simple string goes here");

我已经跟踪了这些线路的崩溃:

freopen("/dev/null", "a", stdout);
freopen("/dev/null", "a", stderr);

我可以通过用以下代码替换行来修复它:

freopen("nul", "a", stdout);
freopen("nul", "a", stderr);

对于那些可能比我更了解比赛内幕的人,我有三个问题:

  1. 这在VS2013中有效但在VS2017中崩溃(没有操作系统更改)。那是为什么?
  2. 将Windows定位为将所有stdout / stderr输出重定向为空时,正确方式是什么,以至于printf不会产生任何可见输出?
  3. 有一种安全的跨平台方式吗?我不一定在寻找插入标准的东西,而是每个主要桌面目标(windows,linux,mac)都能使用的东西。
  4. 修改

    似乎没有可移植的方式来做到这一点,所以我选择了旧的平台特定代码。

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

2 个答案:

答案 0 :(得分:2)

这是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中工作 - 根据我所知道的一切,它不应该有。

答案 1 :(得分:1)

  
      
  1. 这在VS2013中有效但在VS2017中崩溃(没有操作系统更改)。那是为什么?
  2.   

因为MS决定应该改变。 C或C ++中的任何内容都不要求任何替代方案应该具有您所追求的效果,因为freopen()的第一个参数的解释是实现定义的。不同的实现可以以不同的方式定义它。

对于它的价值,/dev/null是一种UNIX主义。 Windows通常不具有该名称的文件,并且它无论如何都不像UNIX那样在文件系统上提供设备文件。因此,如果您的代码在Windows上使用MSVC ++ 2013,则该实现必须为其提供特殊情况行为。

  
      
  1. 将Windows定位为将所有stdout / stderr输出重定向为空的正确方法是什么,这样printf就不会生成任何可见的内容   输出
  2.   

类似于UNIX /dev/null的Windows设备名为nul(更常见的是NUL - 就像常规文件名一样,大小写不重要)。我说使用这是一个不错的选择,但它仍然依赖于实现。

  
      
  1. 有一种安全的跨平台方式吗?我不一定在寻找插入标准的东西,而是寻找某种东西   每个主要桌面目标(windows,linux,mac)都可以使用。
  2.   

这基本上是C或C ++实现的问题,而不是运行该实现的平台。但是,大多数实现都提供了与fopen()freopen()一起使用的文件名,它们与shell和操作系统的其余部分具有相同的重要性。在这方面,VS2013似乎有点奇怪,但它并没有因此而失败。因此,没有,没有单个文件名对每个C和C ++实现都有意义。甚至不能保证任何带有该重要性的文件名。

实际上,您可以依赖/dev/null用于Mac和Linux,而NUL用于Windows。然后,您可以考虑使用条件编译来根据编译环境选择其中一个(参见How do I check OS with a preprocessor directive?)。