2010-11-05 5 views
7

Fond: J'utilise les bibliothèques gérées DirectX 9.0 pour transformer des tableaux de points 3d en coordonnées d'écran 2D. Pour la vitesse, j'utilise UnsafeNativeMethods pour faire toutes les transformations.Pourquoi ce code lance System.ExecutionEngineException

Le problème: Si ma fonction de coupure de ligne personnalisé est utilisé ma demande meurt sans jeter aucune exception, il m'a fallu un certain temps pour comprendre qu'il vomissait un uncatchableSystem.ExecutionEngineException. Je l'ai réduit à se produire à cause des deux dernières lignes de ma fonction d'écrêtage.

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

Lorsque la liste verticesAfterClipping est copiée sur les sommets lineToClip l'objet lineToClip est ensuite transmis à un UnsafeNativeMethod qui transforme ces sommets aux sommets 2d. De tout ce que je peux voir quand je le franchis en mode Débogage, il fonctionne parfaitement, jusqu'à ce qu'il meure.

Je n'arrive tout simplement pas à comprendre ce qui ne va pas. Toute aide serait très appréciée.

Répondre

12

Le problème ne se produit pas réellement dans la ligne qui déclenche une exception. Cela peut juste être un symptôme de quelque chose qui est arrivé plus tôt.

L'exception System.ExecutionEngineException est levée lorsque le CLR détecte que quelque chose s'est très mal passé. Cela peut arriver beaucoup de temps après que le problème est survenu. C'est parce que l'exception est généralement le résultat de la corruption des structures de données internes - le CLR découvre que quelque chose est entré dans un état qui n'a aucun sens. Il jette une exception inaccessible car il n'est pas prudent de continuer.

Ainsi, vous pourriez avoir du code dans une partie du système qui n'est pas du tout corrélée, mais cela ne devient apparent que lorsque ce morceau de code s'exécute. Le code que vous avez montré pourrait bien aller. (Cela peut aussi ne pas être ... Je ne vois rien d'évident, mais je ne connais pas bien les bibliothèques gérées par DX 9. Je ne peux pas voir quelle fonctionnalité de cette méthode nécessite le mot-clé dangereux, par exemple. Malheureusement, cela signifie que vous devez commencer à lancer le réseau un peu plus large. Pratiquement tout ce qui utilise soit un code non sécurisé, soit COM Interop est potentiellement suspect. Ce sera un processus long et fastidieux, malheureusement. Une façon de l'aborder est d'essayer de simplifier progressivement le programme: quel est le plus petit morceau de code pouvant illustrer le problème? (Par exemple, si vous mettez le code que vous avez montré dans une application qui ne contient rien d'autre que l'appel le plus simple possible à cette méthode, échoue-t-il toujours?)

+0

Vous avez raison lorsque vous dites que l'exception ne se produit pas sur ces deux lignes, mais cela se produit comme un résultat de ces deux lignes. J'ai remplacé ces lignes et utilisé un autre tampon temporaire pour copier les sommets écrêtés et tout fonctionne correctement maintenant.J'ai supposé qu'il y avait une sorte de violation d'accès de mémoire se produisant sous les couvertures quand la ligne a été passée aux méthodes natives sûres de directx. – tbridge

+3

Ne supposez pas que l'absence d'ExecutionEngineException signifie que le problème a disparu. Il se peut simplement que le CLR ne le détecte plus. En remplaçant ces lignes, vous pouvez maintenant être dans une situation où les données sont corrompues, mais vous ne recevez plus d'exception. (Le CLR ne peut pas et ne peut pas garantir de lancer ExecutionEngineException chaque fois que quelque chose comme ça va mal, il ne le lance que quand il arrive à le remarquer.) Donc je serais inquiet - j'essayerais certainement d'aller au fond des choses * comment * le crash s'est produit, comme maintenant, il n'y a aucune raison d'être sûr que vous l'avez vraiment corrigé. –

1

J'ai le même problème avec différentes bibliothèques. Dans mon cas, tout a commencé depuis longtemps parce que je devais exécuter une application. Net 32 ​​bits dans un environnement 64 bits. Eh bien, cela me pose beaucoup de problèmes, la compatibilité entre les architectures, ou entre le CLR de votre framework .NET peut être votre problème aussi.

PS: Maintenant, je sais ce que ma peine est d'avoir, mais aucune idée est-il.

Questions connexes