Programmabsturz bei free()



  • Moin zusammen,

    ich habe derzeit ein echt großes Problem an dem ich seit Tagen schwer an verzweifeln bin.
    Google oder Debugprintf's halfen auch nicht sonderlich.

    Das Problem ist, dass das Programm an dem ich schon länger bastel, irgendwann an einer bestimmten Stelle abstürzt.
    Das seltsame daran ist, dass das meist bei free() passiert. An den Pointern die ich freigeben möchte scheint es nicht zu liegen, denn es spielt überhaupt keine Rolle was ich bei besagter Codezeile freigeben möchte.
    Wenn ich soetwas hier mache:

    [...]
    
    {
    	char* blubb = NULL; 
    	blubb = calloc( 1024+1, sizeof(char) ); 
    	free( blubb ); // Crash
    };
    
    free( crashvar );  // Sonst hier
    

    dann stürtzt das Programm beim ersten free() ab. Lass ich das erste free() weg,
    dann stürtzt der eben beim zweiten ab. Da wird wohl irgendwo ein Pointer irgendwelche wichtigen Speicherbereiche überschreiben, nur weis ich nicht wo.

    Ich habe den Quellcode nun bestimmt 10x durchgelesen, optimiert und ggf. noch sicherer gemacht, ganze Unterprogramme (Usereingaben etc.) rausgeschmissen und und und, aber dadurch kommt es immer nur etwas später zu dem Crash.

    Wie würdet ihr hier vorgehen? Ist der Einsatz eines Debuggers hier pflicht oder gibt es auch eine andere Möglichkeit das Problem zu lösen?
    Falls der Einsatz eines Debuggers unumgänglich ist, gibt es eine gute Alternative zum Debugger von GNU, den man in Verbindung mit dem GCC einsetzen kann?

    Falls es hilft:
    Ich verwende den GCC in Verbindung mit Windows XP.
    Für das Programm verwende ich zusätzlich die PostgreSQL-Lib und Posix-Threads.

    LG,
    der Verzweifelter

    PS: Der Code ist etwas zu lang (>1500 zeilen, vereinfacht) um den hier zu Quoten 😞



  • stack überlauf



  • Ein guter Anhaltspunkt wäre es sich den Wert des Pointers anzusehen. Und die Adresse nach alloc mit der nach free zu vergleichen, wenn sie unterschiedlich sind dann mußt du schauen wo du die Adresse veränderst.
    Ich würde dir aber trotzdem zum gdb raten.



  • Nachtrag falls du dich am Commandline-Interface vom gdb störst, dann kannst du auch Eclipse oder sonst ein grafisches Interface nutzen (z.b. "ddd").



  • ^^kann auch sein, dass der heap zerschossen wurde. also entweder wird über einen 'mallocierten' bereich hinausgeschrieben, oder irgendein anderer fehler verursacht wilde schreibzugriffe auf die datenstrukturen des heaps.
    🙂



  • Hoi ho,

    also zum GNU Debugger muss ich leider sagen, dass der mir bis jetzt kaum weiterhilft. Der spuckt mir nämlich nur Assemblercode und Meldungen wie 'No source available for "guard32!?Exported@@YAXXZ() "' aus. Ein anhaltspunkt wo es denn nun geknallt hat, habe ich bisher nicht erhalten.
    Mach ich da was falsch?



  • Mach ich da was falsch?

    Ja ... tolle Antwort wa?

    Hast du mit debuginfo kompiliert? Als Alternative bietet sich noch DDD an, aber es Tools im Sinne von: "Du musst wissen, wie man damit umgeht". Sieh es als Skalpell an, mit dem du eine Operation durchfuehrst. Zum Glueck ist der Schaden geringer und du hast mehr Versuche zum Ueben.

    Verdammt, DDD wurde schon genannt ...



  • Verzweifelter schrieb:

    Hoi ho,

    also zum GNU Debugger muss ich leider sagen, dass der mir bis jetzt kaum weiterhilft. Der spuckt mir nämlich nur Assemblercode und Meldungen wie 'No source available for "guard32!?Exported@@YAXXZ() "' aus. Ein anhaltspunkt wo es denn nun geknallt hat, habe ich bisher nicht erhalten.
    Mach ich da was falsch?

    Ja, übersetze deine Programme mal mit -g bzw -ggdb. Damit bekommt dein Programm Debug-Symbole, ohne kannst du nur schlecht debuggen. Dann solltest du dir mal zumindest eine kurze Einführung zum gdb ansehen, falls nicht schon geschehen. Im Normal Fall zeigt der dir die genaue Stelle wo es kracht. In deinem Fall macht sich sich valgrind übrigens sehr gut, damit kannst du dir fehlerhafte Speicherzugriffe anzeigen lassen. Gibt es aber soviel ich weiß nicht für Windows. Dein Programm sollte aber problemlos unter Linux laufen, wenn du Posix-Threads und solche nicht Windows-Sachen nutzt.



  • Probier mal das Tool:

    http://duma.sourceforge.net
    http://duma.sourceforge.net/74_75_76_77_78_Debugging_DE.pdf

    Soll ein valgrind Ersatz sein, der auch unter Windows geht.
    Kenn ich bis jetzt nur vom Hören-sagen, aber es ist auch ein Artikel (PDF) zur Benutzung dabei.



  • knivil schrieb:

    ...aber es Tools im Sinne von: "Du musst wissen, wie man damit umgeht". Sieh es als Skalpell an, mit dem du eine Operation durchfuehrst.

    garbage in - garbage out, wie man so schön sagt *grins*
    OP: nix gegen debugger, aber wirf mal 'nen blick auf den code, wo du den mallozierten speicher benutzt und so. oft findet man solche bugs allein durch scharfes hinschauen.
    🙂



  • Hi, das mal voraus:

    [...]
    
    {
    	char* blubb = NULL; 
    	char* temp = NULL;  
    	blubb = calloc( 1024+1, sizeof(char) ); 
    	temp = blubb; // umkopieren
    
        if (blubb && (temp == blubb))     // Speicher wirklich bekommen, hat's blubb zerschossen?
    	    free( blubb ); // Crash
    };
    
    free( crashvar );  // Sonst hier
    

    <a href= schrieb:

    C-Guide"> If ptr points to a memory block that was not allocated with calloc, malloc, or realloc, or is a space that has been deallocated, then the result is undefined.

    Das sind schon die wesentlichen Möglichkeiten des Schiefgehens, hilfreich dürfte auch sein, den Pointer gleich nach calloc auf einen temp- pointer umzukopieren und vor dem free auf Gleichheit zu prüfen. Die Wahrscheinlichkeit, temp und blubb wertgleich zu zerhageln, dürfte nahe Null liegen.
    Viel Erfolg bei der Suche! 😉



  • Moin,

    erstmal vielen Dank für die Bemühungen, das weis ich sehr zu schätzen! 🙂
    Die Debug geschichte hatte ich zwar ausprobiert, doch obwohl ich dieses
    Duma irgendwann dann doch noch unter Windows kompilieren konnte,
    war die Lust auch schon futsch ^^

    Nachdem ich ein paar Tage nichts mehr am Programm gemacht hatte um den Wald
    wieder sehen zu können, hatte ich heute nun das ganze noch viel sicherer gemacht.
    Sprich alle callocs mit NULL-Prüfungen und vieles mehr was aber auch nicht half.

    Nun aber habe ich den Fehler scheinbar gefunden. Zwei Dinge hatten dazu geführt:
    1. hätte ich die Problemstelle einfach mal auskommentieren sollen. Denn an der Stelle
    wird ein Datensatzgelesen oder geschrieben (falls X schon existiert). Danach passiert das
    selbe auch bei anderen Tabellen (halt nur andere Felder), aber da funktionierte es. Schön blöd,
    das nächste mal mache ich es richtig, anstatt drumherum zu doktern 😛
    2. schreibe man bei einem 11 Byte langem Feld auch nur 10 Byte statt 40 😃

    Jaja, selbst nach 3 Jahren ANSI C kann man ziemlich "noobige" Fehler machen!

    Gruß und vielen Dank,
    !Verzweifelter


Anmelden zum Antworten