Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

string

c#

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 (\0) 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 \0 in there somewhere:

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

Some things I noticed:

  • if you put the \0 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.

like image 522
Gigi Avatar asked Jan 10 '16 14:01

Gigi


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


1 Answers

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 \0 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.

like image 181
2 revs Avatar answered Sep 19 '22 15:09

2 revs