You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cygwin环境下如何禁止MSVC编译程序在tty中的输出转码

Cygwin环境下MSVC编译程序TTY输出异常转码问题

问题描述

在Cygwin环境下,gcc与MSVC编译的程序在tty中运行时存在输出差异:仅MSVC生成的二进制文件在tty输出8位高位被置1的字符时,会出现异常字符集转码,相关终端输出现象复现如下:

! 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场景下输出被修改,gcc编译的程序输出经过tty时无改动,该现象在Cygwin终端和xterm中均可复现。

经排查转码发生在tty层而非终端层:独立测试显示运行gcc编译的程序时,tty正常返回预期的0xce字节;运行MSVC编译的程序时,相同tty返回的是0x8ec3序列;而使用管道时二者均输出0xce字节。MSVC编译程序通过tty输出的字节长度明显增加,结合Cygwin默认使用UTF-8的特性,推测Cygwin对MSVC程序做了额外的转码处理,而gcc程序不会触发该逻辑。

已尝试的无效方案包括:

  • 设置LC_ALL等环境变量为C locale
  • 在程序入口调用setlocale(0,"")
  • 配置所有_fmode、setmode()等二进制模式组合

测试用输出程序为同一份C源码,仅调用printf或write输出指定字节,MSVC版本使用Windows10环境下的Visual Studio 2019 cl.exe编译。

复现代码

测试源码code.c

#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__
    _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;
}

MSVC编译脚本ms_cl.bat

@echo off

:: 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

编译运行步骤

# 编译MSVC版本
! ms_cl.bat code.c
# 运行测试
! ./code.exe | hexdump
! ./code.exe

# 编译gcc版本
! gcc code.c
# 运行测试
! ./a.exe | hexdump
! ./a.exe

解决方案

该现象是Cygwin对原生Windows程序(非Cygwin-gcc编译、未链接cygwin1.dll的程序)的默认输出转码逻辑导致的:Cygwin的PTY会默认将原生Windows程序的输出从系统默认ANSI代码页转码为UTF-8,你输出的0xce在GBK/CP936代码页中对应字符╬,转成UTF-8就是0xc3 0x8e,和观测到的转码结果完全一致。

要关闭该转码,可通过以下两种方案实现:

方案1:全局设置Cygwin禁用原生程序输出转码

在Cygwin shell的启动配置文件(~/.bashrc或~/.zshrc)中添加如下环境变量:

export CYGWIN="$CYGWIN disable_pcon"

该参数会禁用Cygwin的ConPty适配逻辑,同时关闭对原生Windows程序的默认字符集转码。配置完成后重启Cygwin终端即可生效。

方案2:单程序运行时临时关闭转码

如果不想全局修改配置,可以在运行MSVC编译的程序时,直接通过管道跳过tty转码逻辑:

./code.exe | cat

该方案可以让MSVC编译的程序直接输出原始字节,不再触发Cygwin的自动转码逻辑。


内容的提问来源于stack exchange,提问作者user12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:57:02