【问题标题】:Why is csc.exe crashing when I last left the output encoding as UTF8?为什么我上次将输出编码保留为 UTF8 时 csc.exe 崩溃?
【发布时间】:2015-09-06 12:57:41
【问题描述】:

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

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

用这一行 System.Console.WriteLine(System.Console.OutputEncoding.EncodingName); 运行了一个单行程序,我看到编码是 Western European (DOS)

很好

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

假设我写了一个 C 语言程序来将编码更改为 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 检查了我的 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 个

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

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>

【问题讨论】:

  • 你如何编译和运行这个?
  • @CodeCaster 将代码放在扩展名为 .cs 的文件中,例如aaa1.cs 然后运行 ​​csc aaa1.cs
  • @CodeCaster 开发命令提示符或常规命令提示符有同样的问题。顺便说一句,我也设置了字体关于如何更改字体的步骤,描述了techrepublic.com/blog/windows-and-office/…
  • @CodeCaster 将字体添加到命令提示符的过程本身就是一篇很长的文章。该帖子的大小会增加一倍,因此我链接到了一篇关于这样做的文章。无论如何,许多熟悉此问题的人都会在命令提示符中添加 unicode 字体。这里的问题在于 csc.exe 而不是将字体添加到命令提示符。可以在不向命令提示符添加字体的情况下执行此操作,只是不太清楚。

标签: c# windows command-line csc


【解决方案1】:

好吧,您发现 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() 断言周围的某个地方。我可以看到返回 E_FAIL 语句。然而,它与我发布的版本有所不同,if() 语句被修改,看起来 VSFAIL() 被 RETAILVERIFY() 取代。当他们进行这些更改时出现了问题,可能是在现在命名为 UTF16ToUTF8() 的 UnicodeToUTF8() 中。再次强调一下,我贴的版本其实并没有崩溃,你可以自己运行C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe看看。只有 v4 版本的 csc.exe 有这个 bug。

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

【讨论】:

  • 我的是Microsoft (R) Visual C# Compiler version 4.0.30319.18408
  • 我能看到的唯一“提交错误”按钮是在 microsoft.net 本地页面 connect.microsoft.com/VisualStudio/MSNetNative 上,而这只是进入错误页面,一个试图提交错误的错误! i.imgur.com/Rxy8bW9.png 也许在其他地方有一个提交错误选项可以工作
  • 我试试看还不错。您必须登录。
  • [相比之下] 如果我点击目录中的 powershell,那么就会有一个按钮来提交错误。如果我单击 Visual Studio,我会收到一条消息,说“您已被邀请加入 Visual Studio 的私人 NDA 计划,您可以通过从位于此页面顶部的标题为“程序”的下拉列表中进行选择来查看特定内容。”那时我不知道下一步该点击什么,但点击程序似乎没有多大帮助。
  • 欢迎您提交它,或者如果您看到提交错误选项,请告诉我。顺便说一句,另一个有趣的事情是,是的,chcp 850 有效。如果在执行 chcp 850 之前执行 chcp说代码页是 850。那么为什么 chcp 850 会有所作为我不知道,如果根据 chcp 已经在 850 上。
【解决方案2】:

有不同的文章暗示 Windows 控制台存在许多与 Unicode 相关的错误。文章如:https://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/

这是一种适合我的解决方法。而不是:

csc aaa1.cs

试试这个(这会将 CSC 输出重定向到文件):

csc /utf8output aaa1.cs > aaa1-compilation.log

相关文档:https://msdn.microsoft.com/en-us/library/d5bxd1x2.aspx

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

由 barlop 添加

查看聊天,我们发现执行 csc uuu1.cs&lt;ENTER&gt; uuu1&lt;ENTER&gt; 然后为了防止崩溃,每个 csc 都必须使用 /utf8output AND(出于某种奇怪的未知原因)完成,奇怪的是,使用重定向..所以,csc /utf8output uuu1.cs &gt;asdfsdaf

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

出现问题时,即使 chcp 显示 850,您也应该运行 chcp 850 的原因是,chcp 只会显示输入编码,而 chcp 850 会同时更改输入编码和输出编码,并且我们想要改变输出编码。因此,即使您的输出编码为 65001,chcp 也可能显示 850,而问题仅在于输出编码为 65001

【讨论】:

  • 不起作用i.imgur.com/JPa9xlD.png,甚至完全按照您的方式进行操作.. aaa1-compilation.log 文件没有错误,它只有编译器第一次运行的输出。之后运行 csc,无论 csc 之后是什么,无论 csc 之后是什么,它都不起作用,崩溃发生
  • 对不起,我有点困惑。您链接的图像显示您使用utf8output 参数运行了csc 命令,但我没有看到您将输出重定向到文件。你能澄清一下你到底尝试了什么吗?在我的测试中,让 CSC 与 utf-8 控制台一起工作的唯一方法是结合执行以下两件事:utf8output 参数 + 输出重定向到文件。
  • i.imgur.com/WgfgqlS.png 文件,但即使不进行重定向,我也会崩溃。而崩溃是csc在运行程序后的第二次运行。如此屏幕截图所示。我想要 UTF8 的原因是重定向适用于 UTF8。问题是 csc 在第二次运行时崩溃。
  • 在我的问题中提到的重定向(uuu1>文件)有效(总是有效),因为当我将编码设置为UTF8时它有效。但问题是 UTF8 会导致 csc 然后在下一次运行时崩溃。
  • 好的,我同意你的看法。我只是建议您在第二次运行时也使用重定向来运行 CSC,作为一种解决方法。一旦控制台处于 UTF-8 模式,我也无法使其“正常”工作。从那时起,我一直在打电话给csc /utf8output test.cs &gt; test.log,以避免崩溃。这对您有任何帮助吗?或者您的意思是您希望能够简单地为您的第二次运行执行csc test.cs 而无需任何额外的参数或重定向?
猜你喜欢
  • 2011-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 1970-01-01
  • 2012-01-01
  • 2014-08-12
相关资源
最近更新 更多