【发布时间】:2021-09-23 15:20:20
【问题描述】:
在 Cygwin 下:如何阻止 msvc 编译程序的输出在 tty 中被转码。
在 Cygwin 下:gcc 与 msvc 编译的程序在 tty 下的运行似乎彼此不同。具体来说,当设置了字符的第 8 位时,我在 tty 下看到仅来自 msvc 生成的二进制输出的一些奇怪的字符集转换。我真的很想知道如何关闭这种烦人的行为。考虑:
screen-cap of terminal output (duplicated in a code quote below)
! pwd
/tmp/demo_dir
! echo $LC_ALL "," $LANG "," $LC_CTYPE
, ,
! ./compiled_with_gcc.exe | hexdump
0000000 cece cece
0000004
! ./compiled_with_msvc.exe | hexdump
0000000 cece cece
0000004
! ./compiled_with_gcc.exe
▒▒▒▒!
! ./compiled_with_msvc.exe
╬╬╬╬!
问题是最后一行。 msvc 编译版本的输出与预期不符。上面演示了这两个程序输出相同的数据:所以最后两个输出应该是相同的。但是 tty 版本(没有管道)仅在 msvc 情况下发生更改。 gcc 编译的程序输出通过 tty 毫发无损。此处显示的输出来自 cygwin 终端,但我在 xterm 中看到完全相同的输出差异。
我相信它发生在 tty 而不是终端:因为我用 C 编写了一个独立的 cygwin 程序,它运行 gcc 和 msvc 编译的程序,无论是在管道下还是在未连接到终端的 tty 下.该程序记录从 tty 接收到的实际字节。 当运行 gcc 编译的一个时,tty 会按预期给出 '0xce' 字节。 但是,当通过相同的 tty 收听 msvc 编译程序时,会从 msvc 编译程序接收到一系列“0x8ec3”模式。 当使用管道而不是 tty 时,它们都输出 '0xce'。
这表明 msvc 编译程序通过 tty 输出的宽度增加了。鉴于 cygwin 对 UTF-8 的偏好:很容易怀疑这里出了问题,并且 cygwin 导致了 gcc 编译程序不会发生的额外转码。我希望将其关闭...如何在今天的 cygwin 中成功禁用 UTF-8 翻译。
我注意到,对于通过 tty 访问的 msvc 编译的二进制文件,似乎不尊重 LC_ALL 来阻止这种情况的发生。甚至当 C 程序以 setlocale(0,""); 开头时
生成输出的程序(将使用两个编译器交替编译以进行测试)与您期望的完全一样。两种情况下使用相同的 C 源。它只是调用 printf 或写入一些字节。 msvc版本使用Visual Studio 2019 cl.exe编译(全部运行在Windows10上)。
复制:
#ifndef __CYGWIN__
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <io.h>
#include <fcntl.h>
#include <locale.h>
int main()
{
if(!setlocale(LC_ALL, "")) {
return 77; //historically: non-filesystem permission-denied exit-code
}
#ifndef __CYGWIN__
//Irrelevent: But avoids stackexchange users asking for it.
_setmode(1,_O_BINARY);
_set_fmode(_O_BINARY);
#endif
char *dat="\316\316\316\316";
write(1,dat,4); // printf/fflush here gives same results.
return 0;
}
@echo off
:: ugly msvc build script. ms_cl.bat
:: full of M$ hardcoded paths. Likely includes some unused libraries.
:: Load compilation environment
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat"
:: Invoke compiler with any options passed to this batch file
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30037\bin\Hostx64\x64\cl.exe" /std:c17 %* kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
Build msvc version with:
! ms_cl.bat code.c
Run in terminal with:
! ./code.exe | hexdump
! ./code.exe
Build gcc version with:
! gcc code.c
Run in terminal with:
! ./a.exe | hexdump
! ./a.exe
请注意,相同的程序在十六进制中具有相同的输出,但输出转码的方式不同。在我的用例中,msvc 是“错误的”。
显然,我怀疑 M$ 正在做一些翻译:所以我尝试了 _fmode setmode() 和更多的每种组合来设置二进制模式。我怀疑某些 cygwin UTF-8 检测失败的情况,因此尝试将 LC_ALL 等设置为纯“C”模式并在 shell 中导出。我同样尝试在 msvc 源中设置语言环境。
Cygwin 做了很多工作来在 windows 下创建一个类似 unix 的环境。鉴于上面的 hexdumps,我只能猜测 Cygwin(或一些隐藏的 msvc 控制台层)在这里做了一些非常专业的事情并妨碍了我。这可能与 cygwin 迁移到 ConPty 有关。无论哪种方式。我想帮忙把它关掉。
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。
标签: c visual-c++ cygwin tty