我遇到了一个特殊的情况,我在创建某些类型的字符串时遇到以下错误:
写入调试信息时出现意外错误 - '错误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重现
如果字符串很短,则不会发生.
编辑:以下评论中提供更多珍贵信息.
知道为什么会这样吗?这是某种虫子吗?
编辑:提交错误,包括评论信息.谢谢大家.
我会稍微谈谈这个问题.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 :)
解决方法应该很容易,在运行时将这个字符串粘合在一起.