Exceptionproblem "this application has requested the runtime to terminate..."


  • Mod

    Nein!
    Das ist vollkommen legal Das ist ein konstanter String. der an den Konstruktor übergeben wird. Dieser Zeiger bleibt gültig. Dann wird das Exception Objekt auf dem Heap erzeugt und geworfen.

    Alles vollkommen legal.



  • Bitte ein Bit schrieb:

    Bei dem Logfile interresiert mich daher nur auf welchen Daten der Thread arbeitet und deren Reihenfolge. Denn da kann man Inkonsistenzen in der Thread-Synchonisation sehen.

    Eigentlich ist das Programm ja so konzipiert, dass die Threads vollkommen unabhängig voneinander laufen (nur lokal Exceptions werfen etc) und das Programm diese Threads nur startet und dann wartet, bis alle beendet sind. Theoretisch müsste ich da doch garnichts synchronisieren weil sich die Threads nirgendwo Speicher teilen, oder vertu ich mich da mit dem const char* in der Exceptionklasse? Weil das Objekt an sich doch für jeden Thread eigens erstellt wird...


  • Mod

    Du vertust Dich nicht mit diesem Zeiger für die Excpetion. Er ist const und er ist ein String der durch den Compiler in einem Code-Segment abgelegt wird. Er ist also für die Dauer der gesamten Laufzeot des Programmes gültig.



  • Er ist also für die Dauer der gesamten Laufzeot des Programmes gültig.

    Danke! Genau das wollte ich wissen. 🙂

    @robinlench:

    Bei solchen Programmen musst du immer damit rechnen das dein Programm an allen möglichen Stellen (auch WinAPI Funktionsaufrufe) unterbrochen werden kann sofern diese nicht atomar sind. Zwischen den einzelnen erzeugten Thread's sehe ich da keine Probleme, aber zwischen den erzeugten Thread's und dem Hauptthread.

    Nächste dumme Frage. Kann es sein das die Anweisung throw nicht atomar ist ? Kann es sein das die Exception zwar geworfen wird und der Thread als beendet markiert wird, er aber gerade in diesem Moment durch den Hauptthread gestört wird, welche gerade dummerweise alle Thread beenden und löschen will ???

    Kann es sein das der Thread beendet und gelöscht wird bevor die entsprechende Exception-Funktion aufgerufen wurde ????



  • Was bedeutet atomar?

    Bitte ein Bit schrieb:

    Kann es sein das der Thread beendet und gelöscht wird bevor die entsprechende Exception-Funktion aufgerufen wurde ????

    Eigentlich nicht, da dies auch den Fehler hervorruft, und zwar instant (bei wenigen 100 Threads).

    void execute() {
                int count = 1000;
                for( int i=0; i<count; i++ ) {
                    subtest * a = new subtest( i );
                    array.push_back( a );
                    array.at(i)->thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)threadfunktion, array.at(i),0, 0 );
                    //Sleep(1); // wird diese Anweisung ausgeführt, reduziert sich die Häufigkeit des Fehlers deutlich
                }
                Sleep(10000); // Hier wird einfach gewartet bis die Threads ziemlich sicher fertig sind
                for( int i=0; i<array.size(); i++ ) {
                    WaitForSingleObject(array.at(i)->thread, INFINITE);
                    CloseHandle( array.at(i)->thread );
                    delete array.at(i);
                }
                array.clear();
            }
    

    Das sollte eigentlich auch zeigen, dass der Mainthread nicht in den Threads rumpfuscht während der Laufzeit (der erste Zugriff auf die Threads nach dem Erstellen ist nach diesen 10 Sekunden, der Fehler kommt aber schon viel früher).

    Ich habe übrigens eine sehr seltene Erscheinung des Fehlers mal festgehalten:
    Es kommen mehrere seiten cryptische Zeichen und es piept mehrmals.

    http://i55.tinypic.com/110g50g.jpg

    Diese ganze Ausgabe kann nur von "cout << "Exception caught: " << e->getMessage() << endl;" kommen, da es die einzige Ausgabe im Code ist. Die Sonderzeichen müssen also der Inhalt einer Exception eines der Threads sein. Nach der Ausgabe kam auch die Meldung "... funktioniert nicht mehr und muss beendet werden". (Diese kam auch vorher, nur zusätzlich noch in der Konsole "this application has requested...").


  • Mod

    Dann mach Dein Programm erstmal dicht gegen andere Fehler.
    1. Was passiert bei Dir, wenn sich kein Thread anlegen lässt?
    2. Du benutzt CreateThread aber die CRT. Das erzeugt auch leaks ohne Ende.
    http://blog.m-ri.de/index.php/2007/11/28/createthread-und-die-crt/
    3. Evtl. liegt der Fehler wo ganz anders, CRT? Du greifst zeitgleich aus mehreren Theads auf cout zu. evtl. passiert da der Fehler.



  • Martin Richter schrieb:

    Dann mach Dein Programm erstmal dicht gegen andere Fehler.
    1. Was passiert bei Dir, wenn sich kein Thread anlegen lässt?

    Dafür hab ich auch mal eine Überprüfung eingebaut:

    if( array.at(i)->thread == NULL ) {
                        cout << "Fehler beim Erstellen des Threads.\n";
                        return;
                    }
    

    Martin Richter schrieb:

    2. Du benutzt CreateThread aber die CRT. Das erzeugt auch leaks ohne Ende.
    http://blog.m-ri.de/index.php/2007/11/28/createthread-und-die-crt/

    Nutze jetzt _beginthreadex anstatt von CreateThread, der Fehler kommt immernoch, allerdings eine ganz neue Erscheinung: wieder cryptische Zeichen, Programm reagiert nicht mehr und ein dauerhaftes Piepen (also ca. 5 Pieptöne pro Sekunde, dauerhaft). Hier noch ein Bild:

    http://oi54.tinypic.com/2ykdqa9.jpg

    Martin Richter schrieb:

    3. Evtl. liegt der Fehler wo ganz anders, CRT? Du greifst zeitgleich aus mehreren Theads auf cout zu. evtl. passiert da der Fehler.

    Dazu habe ich einen Mutex angelegt, ändert leider nichts (ausser dass die Ausgabe geordneter ist):

    WaitForSingleObject( mutex, INFINITE );
                    cout << "Exception caught: " << e->getMessage() << endl;
                    ReleaseMutex( mutex );
    

    Hier auch nochmal der aktuelle Code, aus Platzgründen hier: http://pastebin.com/HTJeQ30Q

    Mit diesen Neuerungen tritt der Fehler auch bei jeder Ausführung auf...



  • Eine Funktion ist atomar, wenn diese nicht durch andere Thread's/Prozesse/... unterbrochen werden kann. http://de.wikipedia.org/wiki/Atomare_Operation

    Aber kommen wir zu deinem Problem zurück. Deine Info's sind gut, denn sie zeigen dass das Problem nicht beim Beenden der Thread's liegt. Die Konsole-Ausgabe sieht eher danach aus als wäre der Ausgabestring zerschossen.

    Probiere doch mal bitte aus ob dein Program abstürzt wenn du die Anweisung cout auskommentierst.

    Ähh, deine Mutex Verwendung ist leider falsch. Klar das er nichts macht, denn du erzeugst ihn und wartest später darauf das er in den Signaled Zustand geht, was soweit wie ich weis, dann der Fall ist, wenn der Mutex erzeugt wurde.

    Probiere doch mal den Locking-Mechanism Critical Section http://en.wikipedia.org/wiki/Critical_section um die Anweisung cout.



  • Hier mal wieder eine neue Erscheinung des Fehlers: http://tinypic.com/r/2ex3ksg/7

    Auskommentieren von cout ändert nichts, auch der Critical Section Mechanismus, den ich nun statt dem Mutex eingebaut habe, bringt keine große Veränderung.

    Generell zur Fehlerbeschreibung lässt sich noch sagen, dass die Wahrscheinlichkeit für diesen Fehler mit der Anzahl der Threads steigt. So tritt der Fehler bei 10 Threads eigentlich nie auf, bei 100-1000 aber oft bzw. fast immer.

    kurzes Update: http://pastebin.com/SFfUmQVT



  • Generell zur Fehlerbeschreibung lässt sich noch sagen, dass die Wahrscheinlichkeit für diesen Fehler mit der Anzahl der Threads steigt. So tritt der Fehler bei 10 Threads eigentlich nie auf, bei 100-1000 aber oft bzw. fast immer.

    Seht gut, wir können also den Fehler anständig reproduzieren.

    Hmm, gehe doch mal hin und kompiliere eine Version welche ständig abstürzt und jage sie durch das Program DebugDiag http://www.microsoft.com/downloads/en/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en. Es würde mich mal interresieren was das Program dazu sagt. Alternativ kannst du auch mal den Application Verifier http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c4a25ab9-649d-4a1b-b4a7-c9d8b095df18&displaylang=en ausprobieren. Aber denke daran das Debugging mittels Application Verifier für dein Program auch wieder auszuschalten, da der Application Verifier sich bei jedem Start des Programm dranhängt auch wenn dieser scheinbar ausgeschaltet ist.

    Alternativ können wir jetzt auch mal nach dem Motto try and test vorgehen. Schreibe mal die Exception um so das diese einfach nichts macht, oder die Exception Nachricht lokal speichert (auch wenn dies der Fehler nicht sein sollte),... Wir wollen dadurch einfach nur den Fehler finden.

    class Ex 
    {
      public:
        char ex[64];
        Ex( const char* e ) 
        {
          strcpy(ex, e);
        }
        const char* getMessage() 
        {
          return ex;
        }
    }
    


  • Die umgeschriebene Klasse ändert auf den ersten Blick erstmal nichts.

    Hier eine Logfile, erstellt mit Debug Diagnostic Tool: http://pastebin.com/09jVpJpM

    Der Exit-Code für die Threads sowie das ganze Programm ist halt immer 0xC0000005. Habe gelesen dass dann irgendwie eine Zugriffsverletzung vorliegt. Genauer kenn ich mich aber so hardwarenah leider nicht aus...

    Edit:
    Habe das ganze testweise in Visual Studio aufgesetzt, klappt einwandfrei... soviel dann zu MinGW. Nach einer solchen tagelangen Fehlersuche fällt mir der Umstieg nicht schwer, danke an alle die geholfen haben, mitzusuchen!


Anmelden zum Antworten