谁能解释一下为什么我在 Windows 控制台中运行一个简单的 C++ 程序时得到的输出在通过管道传输到 more
命令时有点乱码。
代码如下:
#include <iostream>
int main()
{
for(int i=101; i<=120; ++i){
std::cerr << " cerr " << i << std::endl;
if(i%5==0){
std::cout << " cout " << i << std::endl;
}
}
}
这两个命令在前几行之后都会产生乱码输出。每次运行的输出都不同。示例如下:
我的代码.exe |更多
...
cerr 117
cerr 118
er cout 105
1 cout 110r
1 cout 1159
cerr 120
cout 120
mycode.exe > nul |更多
...
cerr 114
cerr 115
6 cerr 11
cerr 117
cerr 118
...
请注意,从水平滚动条可以看出,有些行有很多空格。
在 Linux 上,
./mycode |更多
也会给出乱码的结果,但
./mycode>/dev/null |更多
没有。
没有 more
的输出对于 Windows 和 Linux 都很好:
cerr 101
cerr 102
cerr 103
cerr 104
cerr 105
cout 105
cerr 106
cerr 107
cerr 108
cerr 109
cerr 110
cout 110
cerr 111
cerr 112
cerr 113
cerr 114
cerr 115
cout 115
cerr 116
cerr 117
cerr 118
cerr 119
cerr 120
cout 120
我在 Windows 10 上使用 Visual Studio C++ 2017 Community Edition 版本 15.7.4。该程序以 64 位模式编译为 Release 版本。
我认为这很容易重现并获得相同类型的结果,无论是使用 IDE 还是类似以下内容进行编译:
CL/nologo/D WIN32/D_WIN32_WINNT=0x502/EHsc mycode.cpp
- 这些标志可能不是全部都需要,因为它是一个如此简单的程序,但恰好包含在我通常用于测试的 bat 文件中.
顺便说一句,使用 ./mycode | 的 Linux 输出示例more
不是很奇怪,但它看起来还是有点奇怪:
...
cerr 109
cerr 110
cerr cout 110
111
cerr 112
cerr 113
cerr 114
cerr 115
cerr cout 115
116
cerr 117
...
最佳答案
从我的评论扩展。您的代码没有什么特别出人意料的。如果你将一个程序的输出通过管道传递给不同的东西,默认情况下只有 stdout 被传递给这个程序。 stderr 仍然只是打印在控制台上。因此,在不重定向到 null 的情况下,程序的 stderr 和 more 的输出将同时打印到控制台,并且不会同步,因为 more 命令是 fork 的(?不太确定,但已经足够了)。由于在管道和输入处理中存在延迟,这将扰乱输出顺序。
通过重定向到 null,您只将 stdout 重定向到 null,您的 more 得到空输入,stderr 打印到控制台,所以应该没有干扰,您在 linux 上看到了。在 Windows 上,似乎更多的输出是回车符或类似的东西,我不确定,但这也不是真的没有意外。
如果您正在使用管道并且不希望您的输出被弄乱,那么您总是想要的是以下之一:
# Direct stderr to null, only sends stdout to pipe
prog 2>/dev/null | piper
# Direct stderr to stdout, sends both to pipe
prog 2>&1 | piper
# Direct stdout to /dev/null and stderr to stdout, sends just stdout to pipe
prog 2>&1 1>/dev/null | piper
最后一个看起来有点奇怪,因为 ine 会假设它将 stdout 也重定向到 null,但它会在声明此重定向时重定向它,因为 stdout 正在被定向。
您可能想要第二个变体。
注意:不知道这在 Windows 上如何工作,我使用 arch btw ;-)
关于c++ - 乱码的控制台输出管道 stderr 到更多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59137264/