Обходной путь для C# CodeDom, вызывающий переполнение стека (CS1647) в csc.exe?C#

Место общения программистов C#
Ответить
Anonymous
 Обходной путь для C# CodeDom, вызывающий переполнение стека (CS1647) в csc.exe?

Сообщение Anonymous »

У меня возникла ситуация, когда мне нужно создать класс с большой строкой const. Код, находящийся вне моего контроля, приводит к тому, что сгенерированное дерево CodeDom передается в исходный код C#, а затем компилируется как часть более крупной сборки.

К сожалению, я столкнулся с ошибкой ситуация, при которой, если длина этой строки превышает 335 440 символов в Win2K8 x64 (926 240 в Win2K3 x86), компилятор C# завершает работу с фатальной ошибкой:


Неустранимая ошибка CS1647: выражение слишком длинное или сложное для компиляции рядом с 'int'

MSDN сообщает, что CS1647 — это «переполнение стека в компиляторе» (без каламбура!). Присмотревшись повнимательнее, я обнаружил, что CodeDom «хорошо» оборачивает мою строковую константу длиной 80 символов. Это заставляет компилятор объединять более 4193 фрагментов строк, что, по-видимому, соответствует глубине стека компилятора C # в x64 NetFx. CSC.exe должен внутренне рекурсивно оценить это выражение, чтобы «восстановить» мою единственную строку.

Мой первоначальный вопрос таков: «Знает ли кто-нибудь обходной путь? изменить способ генерации строк генератором кода?" Я не могу контролировать тот факт, что внешняя система использует исходный код C# в качестве промежуточного звена, и я хочу, чтобы это было константой (а не конкатенацией строк во время выполнения).

В качестве альтернативы, как мне сформулировать это выражение так, чтобы после определенного количества символов я все еще мог создать константу, но она состоит из нескольких больших фрагментов?< /strong>

Полная репродукция находится здесь:

// this string breaks CSC: 335440 is Win2K8 x64 max, 926240 is Win2K3 x86 max
string HugeString = new String('X', 926300);

CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
CodeCompileUnit code = new CodeCompileUnit();

// namespace Foo {}
CodeNamespace ns = new CodeNamespace("Foo");
code.Namespaces.Add(ns);

// public class Bar {}
CodeTypeDeclaration type = new CodeTypeDeclaration();
type.IsClass = true;
type.Name = "Bar";
type.Attributes = MemberAttributes.Public;
ns.Types.Add(type);

// public const string HugeString = "XXXX...";

CodeMemberField field = new CodeMemberField();
field.Name = "HugeString";
field.Type = new CodeTypeReference(typeof(String));
field.Attributes = MemberAttributes.Public|MemberAttributes.Const;
field.InitExpression = new CodePrimitiveExpression(HugeString);
type.Members.Add(field);

// generate class file
using (TextWriter writer = File.CreateText("FooBar.cs"))
{
provider.GenerateCodeFromCompileUnit(code, writer, new CodeGeneratorOptions());
}

// compile class file
CompilerResults results = provider.CompileAssemblyFromFile(new CompilerParameters(), "FooBar.cs");

// output reults
foreach (string msg in results.Output)
{
Console.WriteLine(msg);
}

// output errors
foreach (CompilerError error in results.Errors)
{
Console.WriteLine(error);
}


Подробнее здесь: https://stackoverflow.com/questions/960 ... in-csc-exe
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»