【问题标题】:Redirecting standard output - Switched from VS2013 to VS2017, exception on writing重定向标准输出 - 从 VS2013 切换到 VS2017,写入异常
【发布时间】:2017-07-29 14:24:57
【问题描述】:

我最近将一个项目从使用 VS2013 编译器切换到 VS2017,现在以下代码似乎无法正常工作:

#include <windows.h>
#include <Fcntl.h>
#include <io.h>
#include <iostream>
#include <exception>

if( RedirectOutput )
{
    //Setup stdout
    HANDLE handle_stdout = GetStdHandle( STD_OUTPUT_HANDLE );

    int fileDesc_stdout = _open_osfhandle( (long)handle_stdout, _O_TEXT );

    if( fileDesc_stdout == -1 )
    {
        throw std::exception( "fileDesc_stdout is not valid" );
    }

    FILE* new_stdout = _fdopen( fileDesc_stdout, "w" );

    if( !new_stdout )
    {
        throw std::exception( "new_stdout is not valid" );
    }

    FILE old_stdout = *stdout;
    *stdout = *new_stdout;

    std::cout.clear();

    std::cout << "Output Redirected!\n";
}

此代码旨在将标准输出重定向到控制台窗口,可以是启动当前进程的窗口,也可以是通过 AllocConsole 创建的控制台。 (出于测试目的,我添加了最后一行。)

第一次写入 cout 时,会抛出以下异常(否则它不会写入输出并从那时起静默失败):

调试断言失败!

程序:w:\build\MyApp.exe 文件:minkernel\crts\ucrt\src\appcrt\stdio_flsbuf.cpp 线路:26

表达式:("inconsistent IOB fields", stream->_ptr - stream->_base >= 0)

有关您的程序如何导致断言的信息 失败,请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)

我可以看到 stdout 来自 corecrt_wstdio.h,但是当我插入断点并添加 watch 时,它说 stdout 未定义,所以我无法检查值。

有什么想法吗?

【问题讨论】:

  • fyi: "注意:虽然可以通过取消引用和复制有效的 std::FILE* 来创建 std::FILE 类型的本地对象,但使用此类副本的地址在 I/O 函数中是未定义的行为” 来源:en.cppreference.com/w/cpp/io/c 我对此的解读是 *stdout = *new_stdout 是 UB,如果你再写信给 stdout
  • @RichardCritten 所以 2013 年实施中的某些东西使这项工作有效,但从来没有任何保证?

标签: c++ visual-studio visual-studio-2017 redirectstandardoutput


【解决方案1】:

于是我搜索了一下,发现this post on SO.

基本上,我发布的所有代码都可以替换为以下代码:

freopen("CONOUT$", "w", 标准输出);

freopen 的第一个参数是文件名,所以我想知道 CONOUT$/CONIN$ 是否代表一个实际的文件,或者该函数是否将该输入视为特殊情况。

【讨论】:

    猜你喜欢
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    相关资源
    最近更新 更多