我遇到了一个特殊的情况,我在创建某些类型的字符串时遇到以下错误:
写入调试信息时出现意外错误 - '错误HRESULT E_FAIL已从调用COM组件返回.
这个错误对Stack Overflow来说并不新鲜(请参阅此问题和此问题),但所提出的问题与此问题无关.
对我来说,当我创建一个特定长度的const字符串时会发生这种情况,该字符串\0在开头附近的某处包含一个空终止字符().
要重现,首先生成一个适当长度的字符串,例如使用:
var s = new string('a', 3000);
Run Code Online (Sandbox Code Playgroud)
在运行时抓取结果字符串(例如,立即窗口或将鼠标悬停在变量上并复制其值).然后,做出一个const:
const string history = "aaaaaa...aaaaa";
Run Code Online (Sandbox Code Playgroud)
最后,\0在某处放置一个:
const string history = "aaaaaaaaaaaa\0aa...aaaaa";
Run Code Online (Sandbox Code Playgroud)
我注意到的一些事情:
\0接近结束,错误不会发生.知道为什么会这样吗?这是某种虫子吗?
编辑:提交错误,包括评论信息.谢谢大家.
我会稍微谈谈这个问题.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);
}
Run Code Online (Sandbox Code Playgroud)
吞咽异常,tsk,tsk.它会在你的案例的最后一个catch子句中死掉.他们确实深入挖掘了字符串长度问题的逆向工程:
internal const int PdbLengthLimit = 2046; // Empirical, based on when ISymUnmanagedWriter2 methods start throwing.
Run Code Online (Sandbox Code Playgroud)
这与\ 0开始投掷的位置相当接近,我得到了2034.当然,你或其他任何人都无法做到这一点.您可以合理地做的就是在connect.microsoft.com上报告错误.但希望你能看到墙上的文字,它修复的可能性相当小.这是没有人维护的代码,它现在具有"未记录"状态,并且从其他评论来看,这可以追溯到.NET之前很久.不是Ed Maurer :)
解决方法应该很容易,在运行时将这个字符串粘合在一起.