2010-11-05 2 views
7

Справочная информация: Я использую управляемые библиотеки DirectX 9.0 для преобразования массивов трехмерных точек в координаты экрана 2d. Для скорости я использую UnsafeNativeMethods для выполнения всех преобразований.Почему этот код генерирует System.ExecutionEngineException

Проблема: Если моя пользовательская функция линии отсечения используется мое приложение умирает, не бросали какие-либо исключения, это мне потребовалось некоторое время, чтобы понять, что это было бросать неуловимогоSystem.ExecutionEngineException. Я сузил его, чтобы произойти из-за последних двух строк моей функции отсечения.

List<Vector3> verticesAfterClipping = new List<Vector3>; 
public unsafe void ClipLine(Line lineToClip) 
{ 
    this.verticesAfterClipping.Clear(); 

    // Clipping algorithm happens here... (this is psuedo-code of what it does) 
    foreach(Vertex in lineToClip.Vertices) 
    { 
     bool thisIsClipped = // Set to whether this vertex is clipped 
     bool lastWasClipped = // Set to whether last vertex was clipped 

     if(thisIsClipped == false && lastWasClipped == true) 
     { 
      verticesAfterClipping.Add(/* intersection on clipping plane */); 
      verticesAfterClipping.Add(/* thisVertex */); 
     } 
     else if (thisIsClipped == false && lastWasClipped == false) 
     { 
      verticesAfterClipping.Add(/* thisVertex */); 
     } 
     else if (thisIsClipped == true && lastWasClipped == false) 
     { 
      verticesAfterClipping.Add(/* intersection on clipping plane */); 
     } 
    } 

    // THIS IS WHERE BAD THINGS HAPPEN 
    lineToClip.Vertices = new Vertex[verticesAfterClipping.Count]; 
    verticesAfterClipping.CopyTo(lineToClip.Vertices, 0); 
} 

Когда verticesAfterClipping список копируется в lineToCliplineToClip вершин объект и затем передают на UnsafeNativeMethod, который преобразует эти вершины в 2d вершин. Из всего, что я вижу, когда я перехожу через него в режиме отладки, он работает полностью нормально, пока он просто не умрет.

Я просто не могу понять, что не так. Любая помощь приветствуется.

ответ

12

Проблема может не возникать в строке, которая генерирует исключение. Это может быть лишь признаком того, что произошло раньше.

Исключение составляет System.ExecutionEngineException, когда CLR обнаруживает, что что-то пошло ужасно неправильно. Это может произойти через некоторое время после возникновения проблемы. Это связано с тем, что исключение обычно является результатом коррупции внутренних структур данных - CLR обнаруживает, что что-то попало в состояние, которое не имеет смысла. Он выдает исключение, исключающее, так как это не безопасно.

Таким образом, у вас может быть какой-то код в какой-то совершенно несвязанной части системы, которая что-то развращает, но это становится очевидным только при выполнении этой конкретной части кода. Код, который вы показали, может быть очень хорошим. (Это также может быть не так ... Я не вижу ничего очевидного неправильно, но тогда я не знаю хорошо управляемых библиотек DX 9. Я не вижу, какая функция этого метода требует, например, ключевого слова unsafe.)

К сожалению, это означает, что вам необходимо начать отливать сеть немного шире. Практически все, что использует либо небезопасный код, либо COM-взаимодействие потенциально подозрительно. К сожалению, это будет долгий и утомительный процесс. Один из способов, по которым вы можете приблизиться к нему, - попытаться постепенно упростить программу: какой самый маленький фрагмент кода может показать проблему? (Например, если вы поместили код, который вы показали там, в приложение, которое не содержит ничего другого, кроме простейшего возможного вызова этого метода, все равно не работает?)

+0

Вы правы, когда говорите, что исключение не встречается в этих двух строках, но оно происходит как РЕЗУЛЬТАТ этих двух линий. Я заменил эти строки и использовал другой временный буфер для копирования обрезанных вершин, и теперь все работает нормально.Я предположил, что было какое-то нарушение доступа к памяти, которое происходит под обложками, когда линия была передана небезопасным родным методам directx. – tbridge

+3

Не предполагайте, что отсутствие ExecutionEngineException означает, что проблема исчезла. Может быть, CLR больше не обнаруживает его. Заменяя эти строки, вы можете оказаться в ситуации, когда данные повреждаются, но вы больше не получаете исключения. (CLR не гарантирует и не может бросить ExecutionEngineException в любое время, когда что-то вроде этого идет не так, и это только бросает его, когда это случается, чтобы заметить.) Таким образом, я был бы обеспокоен - я определенно пытаюсь добраться до основания * как * произошел сбой, так как сейчас нет причин быть уверенным, что вы действительно исправили его. –

1

У меня такая же проблема с различными библиотеками. В моем случае все началось задолго до того, потому что я должен был запустить 32-разрядное приложение .net в 64-битной среде. Ну, это вызывает у меня много проблем, совместимость между архитектурами или между CLR вашей платформы .NET может быть и вашей проблемой.

PS: Теперь я знаю, что моя беда не только имеют ни малейшего представления, где это.

Смежные вопросы