Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
126 views
in Technique[技术] by (71.8m points)

C# won't compile a long const string with a near the beginning

I've run into a peculiar case where I get the following error when creating certain types of string:

Unexpected error writing debug information -- 'Error HRESULT E_FAIL has been returned from a call to a COM component.'

This error is not new to Stack Overflow (see this question and this question), but the problems presented have nothing to do with this one.

For me, this is happening when I create a const string of a certain length that includes a null-terminating character () somewhere near the beginning.

To reproduce, first generate a string of appropriate length, e.g. using:

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

Grab the resulting string at runtime (e.g. Immediate Window or by hovering over the variable and copying its value). Then, make a const out of it:

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

Finally, put a in there somewhere:

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

Some things I noticed:

  • if you put the near the end, the error doesn't happen.
  • Reproduced using .NET Framework 4.6.1 and 4.5
  • Doesn't happen if the string is short.
  • Edit: even more precious info available in the comments below.

Any idea why this is happening? Is it some kind of bug?

Edit: Bug filed, including info from comments. Thanks everybody.

question from:https://stackoverflow.com/questions/34706411/c-sharp-wont-compile-a-long-const-string-with-a-0-near-the-beginning

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'll noodle about this issue a little bit. This issue occurs both in VS2015 and earlier versions. So nothing directly to do with the C# compiler itself, this goes wrong in the ISymUnmanagedWriter2::DefineConstant2() implementation method. ISymUnmanagedWriter2 is a COM interface, part of the .NET infrastructure that all compilers use. And used both by Roslyn and the legacy C# compiler.

The comments in the Roslyn source code (actually dates back to the CCI project) that uses the method are illuminating enough, that there is trouble with this method was discovered before:

// 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);
}

Swallowing exceptions, tsk, tsk. It dies on the last catch clause in your case. They did dig a little deeper to reverse-engineer the string length problem:

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

Which is fairly close to where the starts throwing, I got 2034. Nothing much that you or anybody else here can do about this of course. All you can reasonably do is report the bug at connect.microsoft.com. But hopefully you see the writing on the wall, the odds that it will get fixed are rather small. This is code that nobody maintains anymore, it now has 'undocumented' status and judging from other comments this goes back long before .NET. Not Ed Maurer either :)

Workaround ought to be easy enough, glue this string together at runtime.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...