当前位置:  开发笔记 > 编程语言 > 正文

C#不会在开头附近编译一个带有\ 0的长const字符串

如何解决《C#不会在开头附近编译一个带有\0的长const字符串》经验,为你挑选了1个好方法。

我遇到了一个特殊的情况,我在创建某些类型的字符串时遇到以下错误:

写入调试信息时出现意外错误 - '错误HRESULT E_FAIL已从调用COM组件返回.

这个错误对Stack Overflow来说并不新鲜(请参阅此问题和此问题),但所提出的问题与此问题无关.

对我来说,当我创建一个特定长度的const字符串时会发生这种情况,该字符串\0在开头附近的某处包含一个空终止字符().

要重现,首先生成一个适当长度的字符串,例如使用:

var s = new string('a', 3000);

在运行时抓取结果字符串(例如,立即窗口或将鼠标悬停在变量上并复制其值).然后,做出一个const:

const string history = "aaaaaa...aaaaa";

最后,\0在某处放置一个:

const string history = "aaaaaaaaaaaa\0aa...aaaaa";

我注意到的一些事情:

如果你\0接近结束,错误不会发生.

使用.NET Framework 4.6.1和4.5重现

如果字符串很短,则不会发生.

编辑:以下评论中提供更多珍贵信息.

知道为什么会这样吗?这是某种虫子吗?

编辑:提交错误,包括评论信息.谢谢大家.



1> Hans Passant..:

我会稍微谈谈这个问题.VS2015和早期版本都会出现此问题.所以没有与C#编译器本身直接相关,这在ISymUnmanagedWriter2 :: DefineConstant2()实现方法中出错了.ISymUnmanagedWriter2是一个COM接口,是所有编译器使用的.NET基础结构的一部分.并由Roslyn和传统的C#编译器使用.

使用该方法的Roslyn源代码(实际上可以追溯到CCI项目)中的注释足够启发,以前发现此方法存在问题:

// EDMAURER If defining a string constant and it is too long (length limit is undocumented), this method throws
// an ArgumentException.
// (see EMITTER::EmitDebugLocalConst)

try
{
    this.symWriter.DefineConstant2(name, value, constantSignatureToken);
}
catch (ArgumentException)
{
    // writing the constant value into the PDB failed because the string value was most probably too long.
    // We will report a warning for this issue and continue writing the PDB.
    // The effect on the debug experience is that the symbol for the constant will not be shown in the local
    // window of the debugger. Nor will the user be able to bind to it in expressions in the EE.

    //The triage team has deemed this new warning undesirable. The effects are not significant. The warning
    //is showing up in the DevDiv build more often than expected. We never warned on it before and nobody cared.
    //The proposed warning is not actionable with no source location.
}
catch (Exception ex)
{
    throw new PdbWritingException(ex);
}

吞咽异常,tsk,tsk.它会在你的案例的最后一个catch子句中死掉.他们确实深入挖掘了字符串长度问题的逆向工程:

internal const int PdbLengthLimit = 2046; // Empirical, based on when ISymUnmanagedWriter2 methods start throwing.

这与\ 0开始投掷的位置相当接近,我得到了2034.当然,你或其他任何人都无法做到这一点.您可以合理地做的就是在connect.microsoft.com上报告错误.但希望你能看到墙上的文字,它修复的可能性相当小.这是没有人维护的代码,它现在具有"未记录"状态,并且从其他评论来看,这可以追溯到.NET之前很久.不是Ed Maurer :)

解决方法应该很容易,在运行时将这个字符串粘合在一起.

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有