gpt4 book ai didi

c# - 为什么在我上次将输出编码保留为 UTF8 时 csc.exe 崩溃?

转载 作者:可可西里 更新时间:2023-11-01 13:53:32 29 4
gpt4 key购买 nike

我正在遇到或遇到了一件非常奇怪的事情。

我想知道其他人是否有以及为什么会这样。

使用此行运行单行程序 System.Console.WriteLine(System.Console.OutputEncoding.EncodingName); 我看到编码是 Western European (DOS)

很好

这是一些代码页的列表1200 Unicode65001 utf-8Windows-1252 西欧 (Windows)850 西欧 DOS 来自https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx

假设我编写了一个 C sharp 程序来将编码更改为 utf-8

class sdf
{
static void Main(string[] args)
{
System.Console.WriteLine(System.Console.OutputEncoding.EncodingName);
System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(65001);
System.Console.WriteLine(System.Console.OutputEncoding.EncodingName);
}
}

它工作,它打印

Western European (DOS)
Unicode (UTF-8)

现在,当我再次运行 csc 时,csc 崩溃了。

enter image description here

我用 memtest 检查了我的 RAM 14 个小时,8 次通过。我运行了 chkdsk 我的硬盘,一切正常。这绝对不是那些,这是一个编码问题。我知道这一点,因为如果我打开一个新的 cmd 提示符,然后运行 ​​csc,它就不会崩溃。

所以运行那个 c sharp 程序,改变了 shell,这样下次只要运行 csc 就会让 csc 本身崩溃,以这种方式崩溃。

如果我编译下面的代码,然后运行它,然后运行 ​​csc,然后运行 ​​csc,或者 csc whatever.cs,我会导致 csc 崩溃。

所以关闭cmd提示符,打开一个新的。

这一次,尝试注释和取消注释程序的第二行

我发现如果第二行(将代码页更改为 850(DOS 西欧)的行)存在,那么下次我运行 csc 时它不会崩溃。

而如果我注释掉第二行,则程序退出并将代码页/编码更改为 UTF-8,然后下一次 csc 运行时,csc 崩溃。

//取消注释最后一行,然后//这会运行,但下次会导致 csc 崩溃。

class asdf
{
static void Main()
{

System.Console.OutputEncoding = System.Text.Encoding.UTF8; //output and to utf8
System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(850);
}
}

我不是唯一遇到过这种事情的人

虽然那里没有找到解释https://social.msdn.microsoft.com/Forums/vstudio/en-US/0e5f477e-0c32-4e88-acf7-d53d43d5b566/c-command-line-compiler-cscexe-immediately-crashes-when-run-in-code-page-65001-utf8?forum=csharpgeneral

我可以通过确保最后一行将代码页设置为 850 来处理它。尽管正如我将解释的那样,这是一个不充分的解决方案..

另外我想知道这是否是 CSC 的一些问题,其他人也有。或任何其他解决方案。

已添加

uuu1.cs

// uuu1.cs
class asdf
{
static void Main()
{

System.Console.InputEncoding = System.Text.Encoding.UTF8;
System.Console.OutputEncoding = System.Text.Encoding.UTF8;

// not unicode. UTF8 means redirection will then work

System.Console.WriteLine("ჵ");

// try redirecting too..

// and try checking for csc crash or not
//System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(850);
//System.Console.InputEncoding =System.Text.Encoding.GetEncoding(850);
//problem is that when that is commented, it breaks the redirection



}
}

添加行/取消注释最后几行

System.Console.OutputEncoding=System.Text.Encoding.GetEncoding(850);

会阻止崩溃,但这是一个不充分的解决方案,因为例如.. 如果我想将程序的输出重定向到一个文件,那么我从头到尾都需要 UTF8,否则它不起作用

这适用于未注释的代码页 850 行

c:\blah>uuu1>r.r<ENTER>  
c:\blah>type r.r <ENTER>
c:\blah>ჵ

如果我取消注释最后几行,从而将代码页更改为 850,那么确保 csc 在下次运行时不会崩溃,但是重定向不起作用并且 r.r 不包含该字符。

添加了 2

Han 的回答让我注意到另一种触发此错误的方式

C:\Users\harvey\somecs3>csc<ENTER>
Microsoft (R) Visual C# Compiler version 4.0.30319.18408
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

warning CS2008: No source files specified
error CS1562: Outputs without source must have the /out option specified

C:\Users\harvey\somecs3>chcp 65001<ENTER>
Active code page: 65001

C:\Users\harvey\somecs3>csc<ENTER> <-- CRASH

C:\Users\harvey\somecs3>

最佳答案

好吧,您发现了 C# 编译器在切换到 UTF-8 时必须将文本输出到控制台的处理方式中的一个错误。它具有 self 诊断功能,以确保从 UTF-16 编码字符串到控制台输出代码页的转换工作正常,如果没有,它会猛击红色大按钮。堆栈跟踪看起来像这样:

csc.exe!OnCriticalInternalError()  + 0x4 bytes  
csc.exe!ConsoleOutput::WideToConsole() + 0xdc51 bytes
csc.exe!ConsoleOutput::print_internal() + 0x2c bytes
csc.exe!ConsoleOutput::print() + 0x80 bytes
csc.exe!ConsoleOutput::PrintString() + 0xb5 bytes
csc.exe!ConsoleOutput::PrintBanner() + 0x50 bytes
csc.exe!_main() + 0x2d0eb bytes

WideToConsole() 的实际代码不可用,最接近的匹配是来自 SSCLI20 发行版的这个版本:

/*
* Like WideCharToMultiByte, but translates to the console code page. Returns length,
* INCLUDING null terminator.
*/
int ConsoleOutput::WideCharToConsole(LPCWSTR wideStr, LPSTR lpBuffer, int nBufferMax)
{
if (m_fUTF8Output) {
if (nBufferMax == 0) {
return UTF8LengthOfUnicode(wideStr, (int)wcslen(wideStr)) + 1; // +1 for nul terminator
}
else {
int cchConverted = NULL_TERMINATED_MODE;
return UnicodeToUTF8 (wideStr, &cchConverted, lpBuffer, nBufferMax);
}

}
else {
return WideCharToMultiByte(GetConsoleOutputCP(), 0, wideStr, -1, lpBuffer, nBufferMax, 0, 0);
}
}

/*
* Convert Unicode string to Console ANSI string allocated with VSAlloc
*/
HRESULT ConsoleOutput::WideToConsole(LPCWSTR wideStr, CAllocBuffer &buffer)
{
int cch = WideCharToConsole(wideStr, NULL, 0);
buffer.AllocCount(cch);
if (0 == WideCharToConsole(wideStr, buffer.GetData(), cch)) {
VSFAIL("How'd the string size change?");
// We have to NULL terminate the output because WideCharToMultiByte didn't
buffer.SetAt(0, '\0');
return E_FAIL;
}
return S_OK;
}

从机器代码判断,崩溃发生在 VSFAIL() 断言周围的某个地方。我可以看到返回的 E_FAIL 语句。然而,它与我发布的版本有所不同,if() 语句已修改,看起来 VSFAIL() 已被 RETAILVERIFY() 取代。当他们进行这些更改时,出现了一些问题,可能是在 UnicodeToUTF8() 中,它现在被命名为 UTF16ToUTF8()。再次强调,我发布的版本实际上并没有崩溃,你可以通过运行 C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe 来自己查看。只有v4版本的csc.exe有这个bug。

真正的bug很难从机器代码中挖掘出来,最好让微软去操心。您可以在 connect.microsoft.com 上提交错误。我没有看到类似的报告,顺便说一句,相当了不起。此错误的解决方法是使用 CHCP 将代码页改回。

关于c# - 为什么在我上次将输出编码保留为 UTF8 时 csc.exe 崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30956834/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com