2010-11-05 31 views
7

Antecedentes: Estoy utilizando DirectX 9.0 Managed Libraries para transformar matrices de puntos 3d en coordenadas de pantalla 2d. Para velocidad utilizo los métodos UnsafeNativeMethods para hacer todas las transformaciones.Por qué este código arroja System.ExecutionEngineException

El problema: Si se utiliza la función de mi línea de recorte a medida mi solicitud muere sin lanzar ninguna excepción, me tomó un tiempo para averiguar que estaba lanzando un inalcanzableSystem.ExecutionEngineException. Lo he reducido a suceder debido a las dos últimas líneas de mi función de recorte.

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

Cuando la lista de verticesAfterClipping se copia en el lineToClip vértices del objeto lineToClip se pasa entonces a un UnsafeNativeMethod que transforma estos vértices a los vértices 2D. De todo lo que puedo ver cuando lo paso en el modo de depuración funciona completamente bien, hasta que simplemente muere.

Simplemente no puedo entender lo que está mal. Cualquier ayuda sería muy apreciada.

Respuesta

12

Es posible que el problema no se esté produciendo en la línea que arroja una excepción. Esto puede ser solo un síntoma de algo que sucedió antes.

La excepción System.ExecutionEngineException se produce cuando el CLR detecta que algo ha ido terriblemente mal. Esto puede pasar un tiempo considerable después de que ocurrió el problema. Esto se debe a que la excepción suele ser el resultado de la corrupción de las estructuras internas de datos: el CLR descubre que algo ha entrado en un estado que no tiene sentido. Lanza una excepción imposible de capturar porque no es seguro proceder.

Por lo tanto, es posible que tenga algún código en alguna parte del sistema que no guarde relación alguna y que corrompa algo, pero esto solo se hace evidente cuando se ejecuta este fragmento de código en particular. El código que has mostrado podría estar bien. (También podría no serlo ... No veo nada obvio, pero no conozco bien las bibliotecas administradas de DX 9. No puedo ver qué función de este método requiere la palabra clave insegura, por ejemplo.)

Lamentablemente, esto significa que debe comenzar a emitir la red un poco más. Prácticamente cualquier cosa que use un código inseguro o interoperabilidad COM es potencialmente sospechoso. Este será un proceso largo y tedioso, por desgracia. Una forma de abordarlo es intentar simplificar gradualmente el programa: ¿cuál es la pieza de código más pequeña que puede ilustrar el problema? (Por ejemplo, si coloca el código que ha mostrado allí en una aplicación que no contiene nada más que la llamada más simple posible a ese método, ¿sigue fallando?)

+0

Tiene razón cuando dice que la excepción no ocurre en esas dos líneas, pero ocurre como RESULTADO de esas dos líneas. Reemplacé esas líneas y usé otro buffer temporal para copiar vértices recortados y todo está funcionando bien ahora.Supuse que se producía algún tipo de violación de acceso a la memoria bajo las cubiertas cuando la línea se pasaba a métodos inseguros de directx nativo. – tbridge

+3

No asuma que la ausencia de ExecutionEngineException significa que el problema se ha ido. Simplemente puede ser que el CLR ya no lo detecte. Al reemplazar esas líneas, es posible que ahora se encuentre en una situación en la que los datos se corrompen, pero ya no obtiene una excepción. (El CLR no garantiza ni puede garantizar tirar ExecutionEngineException en cualquier momento en que algo así salga mal. Solo lo lanza cuando se da cuenta.) Así que estaría preocupado. Definitivamente estaría tratando de llegar al fondo de * cómo * se produjo el bloqueo, como ahora, no hay motivo para estar seguro de que realmente lo ha solucionado. –

1

Tengo el mismo problema con diferentes bibliotecas. En mi caso, todo comenzó mucho antes porque tenía que ejecutar una aplicación .net de 32 bits en un entorno de 64 bits. Bueno, esto me causa muchos problemas, la compatibilidad entre arquitecturas, o entre el CLR de .NET framework puede ser tu problema también.

PD: Ahora sé lo que es mi problema, pero no tienen idea de donde es.

Cuestiones relacionadas