2010-11-05 42 views
7

Sfondo: Utilizzo librerie gestite DirectX 9.0 per trasformare matrici di punti 3D in coordinate schermo 2D. Per velocità uso gli UnsafeNativeMethods per fare tutte le trasformazioni.Perché questo codice genera System.ExecutionEngineException

Il problema: Se viene usata la mia funzione di ritaglio linea personalizzata mia applicazione muore senza gettare eccezioni, ci ho messo un po 'per capire che stava gettando un imprendibileSystem.ExecutionEngineException. L'ho ristretto a causa delle ultime due righe della mia funzione di ritaglio.

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

Quando l'elenco verticesAfterClipping viene copiato i lineToClip vertici dell'oggetto lineToClip viene poi passato ad un UnsafeNativeMethod che trasforma questi vertici di vertici 2d. Da tutto quello che posso vedere quando lo passo in modalità Debug funziona perfettamente, fino a quando non muore.

Semplicemente non riesco a capire cosa c'è che non va. Qualsiasi aiuto sarebbe molto apprezzato.

risposta

12

Il problema potrebbe non essere effettivamente presente nella riga che genera un'eccezione. Questo potrebbe essere solo un sintomo di qualcosa che è accaduto prima.

L'eccezione System.ExecutionEngineException viene generata quando CLR rileva che qualcosa è andato terribilmente storto. Questo può accadere un po 'di tempo dopo che si è verificato il problema. Questo perché l'eccezione di solito è il risultato della corruzione delle strutture di dati interne: il CLR scopre che qualcosa è entrato in uno stato che non ha senso. Genera un'eccezione inafferrabile perché non è sicuro procedere.

Quindi potresti avere del codice in qualche parte del sistema completamente non correlata che corrompe qualcosa, ma questo diventa evidente solo quando questo particolare pezzo di codice viene eseguito. Il codice che hai mostrato potrebbe andar bene. (Potrebbe anche non essere ... Non vedo nulla di ovvio, ma poi non conosco bene le librerie gestite DX 9. Non riesco a vedere quale caratteristica di questo metodo richieda la parola chiave non sicura, per esempio.)

Sfortunatamente, questo significa che è necessario iniziare a lanciare la rete un po 'più ampia. Praticamente qualsiasi cosa che usi sia il codice non sicuro, o l'interoperabilità COM è potenzialmente sospetto. Questo sarà un processo lungo e noioso, purtroppo. Un modo per avvicinarti è provare gradualmente a semplificare il programma: qual è il più piccolo codice che può illustrare il problema? (Ad esempio, se inserisci il codice che hai mostrato lì in un'applicazione che non contiene nient'altro che la chiamata più semplice a quel metodo, fallisce ancora?)

+0

Hai ragione quando dici che l'eccezione non si verifica su queste due righe, ma si verifica come risultato di queste due righe. Ho sostituito quelle linee e ho usato un altro buffer temporaneo per copiare i vertici tagliati e ora tutto funziona correttamente.Supponevo che ci fosse un qualche tipo di violazione di accesso alla memoria che si verificava sotto le copertine quando la linea veniva passata a metodi nativi Directx non sicuri. – tbridge

+3

Non dare per scontato che l'assenza di ExecutionEngineException significhi che il problema è andato via. Potrebbe essere semplicemente che il CLR non lo sta più rilevando. Sostituendo tali linee, ora potresti trovarti in una situazione in cui i dati sono danneggiati, ma non ottieni più un'eccezione. (Il CLR non può e non può garantire di lanciare ExecutionEngineException ogni volta che qualcosa di simile va storto. Lo getta solo quando capita di accorgersene.) Quindi sarei preoccupato - sicuramente cercherò di arrivare al fondo * come * si è verificato il crash, come adesso, non c'è motivo di essere sicuri che tu l'abbia davvero risolto. –

1

Ho lo stesso problema con diverse librerie. Nel mio caso tutto è iniziato molto tempo prima perché dovevo eseguire un'app .net a 32 bit in un ambiente a 64 bit. Beh, questo mi causa un sacco di problemi, la compatibilità tra architetture o tra il CLR del tuo framework .NET potrebbe essere il tuo problema.

PS: Ora so cosa il mio problema è che non hanno idea di dove è.

Problemi correlati