2009-05-12 12 views
2

Es ist mit großer Zögern, dass ich diese Frage stelle, weil ich weiß, dass, wenn Sie denken, dass Sie einen Fehler in etwas wie dem .NET-Framework gefunden haben, es wahrscheinlich nur Sie etwas falsch machen. Nichtsdestoweniger kann ich wirklich nicht herausfinden, was meine gegenwärtige Situation verursacht hat.Ein Fehler in .NET?

Ich baue einen Raytracer in C# und in einem speziellen Fall wird die Return-Anweisung einer Methode nie aufgerufen. Das komische Ding ist, dass völlig unabhängige Dinge beeinflussen, wenn dieses Verhalten stattfindet.

können Sie die problematische Methode siehe hier:

public Primitive FindNearest(ref float distance, Ray ray, ref RayCollision collisionResult) 
{ 
    if (!_initialized) InitUnit(); 

    Primitive hitPrimitive = null; 

    //Search the planes 
    foreach (var plane in RenderEngine.Scene.Planes) 
    { 
     RayCollision collision = plane.Intersect(ray, ref distance); 
     if (collision != RayCollision.Miss) 
     { 
      hitPrimitive = plane; 
      collisionResult = collision; 
     } 
    } 

    if (_spatialStructure == null) 
    { 
     //Default collision detection 
     foreach (Primitive primitive in _primitives) 
     { 
      //RayCollision collision = primitive.Intersect(ray, ref distance); 
      //if (collision != RayCollision.Miss) 
      //{ 
      // hitPrimitive = primitive; 
      // collisionResult = collision; 
      //} 
     } 
    } 
    else 
    { 
     //hitPrimitive = _spatialStructure.GetClosestIntersectionPrimitive(ray, ref distance, out collisionResult); 
     //Console.WriteLine("Was here"); 

     RayCollision collision; 
     Primitive prim = _spatialStructure.GetClosestIntersectionPrimitive(ray, ref distance, out collision); 

     if (collision != RayCollision.Miss) 
     { 
      hitPrimitive = prim; 
      collisionResult = collision; 
     } 
    } 

    return hitPrimitive; 
} 

Nur ein Thread diese Methode ruft und bei jedem Aufruf wird die Console.WriteLine-Anweisung ausgeführt, aber die return-Anweisung wird nie erreicht. Die Methode wird hunderte Male aufgerufen und bei jedem Aufruf wird "wurde hier" auf die Konsole gedruckt.

Wenn ich die zweite foreach (die mit allen Kommentaren) auskommentieren, wird die Return-Anweisung als normal erreicht, aber der auskommentierte Code wird sowieso nie erreicht. Andere Arten der Umstrukturierung des Codes können auch dazu führen, dass er wie beabsichtigt ausgeführt wird, aber wiederum nicht aus irgendeinem Grund, der für mich sinnvoll ist.

Dieses Verhalten sieht eher wie ein Speicherbeschädigungsproblem aus, das man in C finden könnte, also habe ich keine Hinweise, was das verursacht haben könnte - außer einem Fehler in .NET.

Btw, verwende ich die Version von .NET 3.5 SP1.

Update 3

Am Ende stellte sich heraus, dass der Haltepunkt gegessen worden war, weil ich in Release-Modus war. Ich denke du lernst jeden Tag etwas Neues.

Update 2

Es scheint, ich wurde auf das seltsame Verhalten so konzentriert, dass ich nicht den Fehler in meinem Code zu sehen war. Ich habe den Code geändert, um dies widerzuspiegeln, aber ich habe immer noch das Problem, niemals den Breakpoint bei der Return-Anweisung auszulösen - was auf einen Fehler in Visual Studio (2008) und nicht auf .net hinweist. Aber mein Code funktioniert jetzt und ich denke, ich muss mich damit abfinden.

aktualisieren

Hier ist die Demontage ist in der Console.WriteLine-Funktion für die Intensivierung der die letzte bekannte Position, bevor die Strömung schwindet Kontrolle ist (Es gibt keinen Quellcode in Schritt A). Ich kann Assembly nicht lesen, also weiß ich nicht, was es bedeutet, aber es könnte für jemanden da draußen Sinn machen.

0000002a mov   r11,qword ptr [rbx+20h] 
0000002e mov   rax,qword ptr [r11] 
00000031 mov   rdx,rdi 
00000034 mov   rcx,r11 
00000037 call  qword ptr [rax+000001A0h] 
0000003d lea   rdx,[rbp+8] 
00000041 mov   rcx,rbx 
00000044 call  FFFFFFFFFFF0C410 
00000049 jmp   0000000000000050 
0000004b jmp   0000000000000050 
0000004d nop   dword ptr [rax] 
00000050 lea   rsp,[rbp+10h] 
00000054 pop   rdi 
00000055 pop   rbp 
00000056 pop   rbx 
00000057 rep ret   
00000059 push  rbx 
0000005a push  rbp 
0000005b push  rdi 
0000005c sub   rsp,30h 
00000060 mov   rbp,qword ptr [rcx+20h] 
00000064 mov   qword ptr [rsp+20h],rbp 
00000069 lea   rbp,[rbp+20h] 
0000006d lea   rdx,[rbp+8] 
00000071 mov   rcx,qword ptr [rbp+30h] 
00000075 call  FFFFFFFFFF56F3E9 
0000007a nop    
0000007b add   rsp,30h 
0000007f pop   rdi 
00000080 pop   rbp 
00000081 pop   rbx 
00000082 rep ret 
+0

Wie Sie die Rückkehr wissen, ist, nicht erreicht werden ? –

+0

Wie stellen Sie fest, dass "return hitPrimitive" nie erreicht wird? Wenn die Methode nie zurückkehrt, sollten Sie irgendwann mit einer StackOverflowException enden ... –

+0

Mit einem Haltepunkt. Außerdem ist die Variable, der das Ergebnis der Methode zugewiesen wird, immer Null, als ob die Methode nie aufgerufen würde. –

Antwort

1

Woher wissen Sie, dass eine Ausnahme nicht von einer Subroutine ausgelöst wird? Versuchen Sie, alles in einen Versuch/Fang zu wickeln.

+0

Es gibt nichts zwischen der Zeile "Was hier" und der return-Anweisung, die eine Ausnahme auslösen kann - und wenn das passiert, würde das Programm zum Absturz führen (ich habe versucht, eine Exception auszulösen) . –

0

Was passiert in der aufrufenden Methode nach der Ausführung der Ablaufverfolgung?

Wenn die Antwort ist, wie ich es erwarte, "nichts", ist dies fast sicher ein Threading-Problem. Entweder wird Ihr Thread jedes Mal an der gleichen Stelle gesperrt (unwahrscheinlich) oder die Methode, von der aus Sie anrufen, wird zwischen dem Hinzufügen der Methode zum Stack und dem Abrufen des Rückgabewerts von demselben kooptiert oder blockiert.

+0

In Bezug auf das Threading gibt es zwei Threads - einen Worker-Thread, der die ganze Arbeit erledigt, und den Hauptprogramm-Thread, der nur darauf wartet, dass der Worker seine Arbeit vollendet (mit Join()). Andere Threads müssten ein versteckter Thread von .NET sein, obwohl ich nicht sehen kann, was es sein soll. –

2

Die Moral der Geschichte ist, wenn Sie fragen "Ist das ein Fehler in {.NET, C#, Windows}", dann ist die Antwort wahrscheinlich "Nein". Millionen und Millionen von Menschen nutzen diese Dinge, so dass die Wahrscheinlichkeit, dass Sie den Fehler finden, ziemlich klein ist - selbst wenn es einen Fehler gab, wird ihn jemand anders zuerst gefunden haben.

Die Ausnahme wäre ein Fall, wo Sie einer der wenigen Menschen auf der Welt sind, die den Fehler erfahren haben könnten. Das macht es wahrscheinlicher, dass Sie es gefunden haben. Dies kann daran liegen, dass Sie eine Betaversion verwenden oder weil Sie in einer unbekannten Ecke der Software arbeiten.

Aber viele Leute hätten einen Fehler mit "Return-Anweisung nie ausgeführt" gesehen. Da Sie wahrscheinlich nicht der Erste sind, der diesen Fehler sieht, haben Sie wahrscheinlich keinen Fehler gefunden.

Dank der Mann, der mir gesagt, dass ich in der Tat nicht, hatte einen Fehler in der TOPS-10-Betriebssystem gefunden, vor einigen Jahren

+0

Ich hatte irgendwie das Gefühl, dass es so kommen würde, aber ich wusste nicht, was ich sonst tun sollte. Wie auch immer, ich habe ein paar nützliche Dinge darüber gelernt, wie man Debugging angehen kann und mein Problem gelöst hat, also war es das wert. –