C# 当我上次将输出编码保留为UTF8时,为什么csc.exe会崩溃?

C# 当我上次将输出编码保留为UTF8时,为什么csc.exe会崩溃?,c#,windows,command-line,csc,C#,Windows,Command Line,Csc,我遇到了一件非常奇怪的事情 我想知道其他人是否有,为什么会这样 已经用这一行System.Console.WriteLine(System.Console.outpunecoding.EncodingName)运行了一行程序我看到编码是西欧(DOS) 好的 下面是一些代码页的列表 1200 Unicode和65001 utf-8和Windows-1252西欧(Windows)和850西欧DOS来自 假设我写了一个C sharp程序,将编码改为utf-8 class sdf { static

我遇到了一件非常奇怪的事情

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

已经用这一行
System.Console.WriteLine(System.Console.outpunecoding.EncodingName)运行了一行程序我看到编码是
西欧(DOS)

好的

下面是一些代码页的列表
1200 Unicode
65001 utf-8
Windows-1252西欧(Windows)
850西欧DOS
来自

假设我写了一个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崩溃了

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

因此,运行c sharp程序,改变shell,使得下一次运行csc时,csc本身会以如此大的方式崩溃

如果我编译下面的代码,然后运行它,然后运行csc,然后运行csc,或者csc which.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); 
  }
}
我不是唯一一个遇到这种事情的人

虽然没有找到任何解释

我可以通过确保最后一行将代码页设置为850来解决这个问题。尽管我会解释这是一个不合适的解决方案

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

已添加

uu1.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.outpunecoding=System.Text.Encoding.GetEncoding(850)

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

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

c:\blah>uuu1>r.r<ENTER>  
c:\blah>type r.r <ENTER>  
c:\blah>ჵ  
c:\blah>uu1>r.r
c:\blah>键入r.r
c:\blah>ჵ  
如果我取消最后几行的注释,从而将代码页更改为850,那么确保csc不会在下一次运行时崩溃,但重定向不起作用,r.r不包含该字符

增加了2个

韩的回答让我注意到了触发这个错误的另一种方式

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:\Users\harvey\somecs3>csc
Microsoft(R)Visual C#编译器版本4.0.30319.18408
适用于Microsoft(R).NET Framework 4.5
版权所有(C)微软公司。保留所有权利。
警告CS2008:未指定源文件
错误CS1562:没有源的输出必须指定/out选项
C:\Users\harvey\somecs3>chcp 65001
活动代码页:65001
C:\Users\harvey\somecs3>csc

有不同的文章提示Windows控制台存在许多与Unicode相关的错误。例如:

以下是一个适合我的解决方法。而不是:

csc aaa1.cs
尝试以下操作(将CSC输出重定向到文件):

相关文件:

在某些国际配置中,编译器输出无法在控制台中正确显示。在这些配置中,请使用/utf8output并将编译器输出重定向到文件

由巴洛普添加

查看chat,我们发现执行
csc uuu1.cs
uu1
,然后为了防止崩溃,每个csc都必须使用/utf8output完成,而且(出于一些奇怪的未知原因),奇怪的是,还需要重定向..因此,
csc/utf8output uuuu1.cs>asdfsdaf

不过,Han的解决方法更好,只要在
uuu1
之后运行chcp 850(或您使用的任何代码页),即使chcp说是850,您仍然必须执行chcp 850。然后csc将正常运行


出现问题时,即使chcp显示850,您也应该运行chcp 850的原因是,chcp将仅显示输入编码,尽管chcp 850将同时更改输入编码和输出编码,我们希望更改输出编码。因此,即使您的输出编码为65001,并且问题处于打开状态,chcp也可以显示850当输出编码为65001时,您发现C#编译器在处理切换到UTF-8时必须向控制台输出文本的方式中存在一个错误。它有一个自诊断功能,以确保从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()断言的某个地方。我可以看到return E_FAIL语句。但是它与我发布的版本不同,if()语句被修改,看起来VSFAIL()被RETAILVERIFY()替换。当他们进行这些更改时,可能在UnicodeToUTF8()中发生了一些故障现在名为UTF16ToUTF8()。再次强调,我发布的版本实际上没有崩溃,您可以通过运行C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe亲自查看。只有v4版本的csc.exe存在此错误

从机器代码中很难找出真正的错误,最好让微软担心一下。你可以在connect.micros上存档错误
/*
 * 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;
}