Segmentation fault



  • Hi Leute,

    Ich habe seit einiger Zeit einen komischen Fehler beim ausführen eines selbstgeschriebenen Programms.
    Das kompilieren funktioniert ohne Fehler, Warnungen, aber wenn ich es ausführen will, dann schreibt er mir sofort ein 'Segmentation fault' hin. Das merkwürdige daran ist, dass es mal funktioniert hat, ohne das ich den Quellcode verändert habe! Ich hab mich auch schon im Internet ein bisschen über den 'Segmentation fault' belesen. Es hat wohl was mit der Hardware zu tun und nicht mit Linux oder sowas. Bei Windows macht sich sowas durch einen schweren Ausnahmefehler bemerkbar. Das kann zum Beispiel durch einen nicht korrekt addressierten Pointer hervorgerufen werden, bloß wie beseitigt man sowas???
    Nun, als nächstes gibts da die Methode mit einem Debugger, z.B. 'gdb'. Dabei tue ich folgendes:

    >gdb meinprog
      GNU gdb 5.3
      Copyright 2002 Free Software Foundation, Inc.
      GDB is free software, covered by the GNU General Public License, and you are
      welcome to change it and/or distribute copies of it under certain conditions.
      Type "show copying" to see the conditions.
      There is absolutely no warranty for GDB.  Type "show warranty" for details.
      This GDB was configured as "i586-suse-linux"...
      (gdb) run
      Starting program: /home/ringostarr/Programmierung/meinprog/meinprog
    
      Program received signal SIGSEGV, Segmentation fault.
      0x08052295 in main ()
      (gdb) bt
      #0  0x08052295 in main ()
      #1  0x40122857 in __libc_start_main () from /lib/libc.so.6
      (gdb)
    

    was kann man damit wohl anfangen???

    Für hilfe währe ich natürlich sehr dankbar!!!



  • Hast du die LibC neu erstellt?
    Wenn nein mach bei deinem Prog mal ein make clean und erstell danach neu.
    Weißt du an welcher Stelle der SIGSEGV auftritt im C Source? Wenn ja - teste mal, ob du irgendwo einen NULL Pointer hast, oder ein Memory Leak, oder Speicher schon deallokiert hast. Oder ob das Objekt, was du nutzt überhaupt Initialisiert ist.

    Segmentation Fault ist ned Schwerer Ausnahmefehler, sondern das selbe wie eine Access Violation. Also zugriff auf Speicher, der dem Programm nicht zusteht. Z.B. auf NULL



  • Hallo,

    __libc_start_main
    

    das sieht mir aber eher danach aus, als dass dein Programm gar nicht erst
    gestartet werden kann. Das Programm stuerzt ab, bevor main() ueberhaupt
    vollstaendig initialisiert worden ist. Das ist natuerlich ein richtig schlechter
    Ausgangspunkt.

    1.) Koennte es sein, dass deine libc durch irgendwas kaputt gegangen ist. Du
    koenntest einfach mal versuchen, die libc neu zu installieren. Merkwuerdig ist
    allerdings, dass andere Programme offensichtlich _nicht_ davon betroffen sind

    2.) Du sagtest, dass es evtl. an deiner Hardware liegen koennte. In diesem Fall
    bleibt dir ueberhaupt nichts anderes uebrig, als zu versuchen diese Hardware-
    komponente zu lokalisieren und ggf. durch eine neue Hardwarekomponente zu
    ersetzen.

    Da du sagst, dass es manchmal funktioniert und manchmal nicht, tippe ich eher
    auf Punkt 2, da, im Falle das die libc kaputt sein sollte, dieser Fehler eher
    nicht _nur_mal_ auftreten wuerde, sondern generell, womit dann auch andere
    Programm davon betroffen waeren.

    Hmmm...es ist sehr merkwuerdig, sry falls ich dir nicht richtig weiterhelfen
    kann.

    mfg
    v R



  • virtuell Realisticer schrieb:

    Hallo,

    __libc_start_main
    

    das sieht mir aber eher danach aus, als dass dein Programm gar nicht erst
    gestartet werden kann. Das Programm stuerzt ab, bevor main() ueberhaupt
    vollstaendig initialisiert worden ist. Das ist natuerlich ein richtig schlechter
    Ausgangspunkt.

    Ich mag mich irren, aber da das ein backtrace ist heißt das doch nur dass __libc_start_main die Funktion main aufgerufen hat und main einen Fehler produziert hat.

    @ringo: versuch doch mal in der main-funktion ein printf einzusetzen, so dass du es solaneg hin und herschiebst bis es vorm SIGSEGV bzw. gerade nicht mehr kommt. Oder lass dir mit objdump -Sd mal den Assemblercode mit reingemsichtem SOucrecode anzeigen. Da solltest du dann die Fehlerhafte instruktion (0x08052295) finden und kurz darüber die Codezeile die Ärger macht.



  • Hallo,

    das mag sein, jedoch steht hier:

    #1  0x40122857 [b]in[/b] __libc_start_main () from /lib/libc.so.6
    

    mfg
    v R



  • Da steht aber dadrüber:

    Program received signal SIGSEGV, Segmentation fault. 
      0x08052295 in main () 
      (gdb) bt 
      #0  0x08052295 in main ()
    

    Ergo das Programm hat den SIGSEGV in main an Adresse 0x08052295 bekommen, main wurde an adresse 0x40122857 in __libc_start_main () aufgerufen.

    Hier noch ein Beweisstück 😉

    triphoenix:~/root$ cat > segv.c
    int main() {
            *((char *)0) = 5;
            return 0;
    }
    triphoenix:~/root$ gcc segv.c -o segv
    triphoenix:~/root$ gdb ./segv
    GNU gdb 5.3
    Copyright 2002 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "i686-pc-linux-gnu"...
    (gdb) run
    Starting program: /mnt/data/segv
    
    Program received signal SIGSEGV, Segmentation fault.
    0x08048318 in main ()
    (gdb) bt
    #0  0x08048318 in main ()
    #1  0x400427a6 in __libc_start_main () from /lib/libc.so.6
    (gdb)
    

    Ich denke dieses Programm ist nicht wegen meiner libc abgestürzt 😉

    PS: @fragesteller: hast du dein programm mal mit dem zusatzparameter -g kompiliert? Ich sehe gerade, dann liefert gdb die fehlerhafte codezeile sogar.



  • Ich denke dieses Programm ist nicht wegen meiner libc abgestürzt

    Nein, in der Tat nicht, dann hab ich mich geirrt.

    triphoenix:~/root$ cat > segv.c
    int main() {
    *((char *)0) = 5;
    return 0;
    }

    Du programmierst nicht wirklich so, oder? 😃

    mfg
    v R



  • triphoenix:~/root$ cat > segv.c
    int main() {
    *((char *)0) = 5;
    return 0;
    }

    Du programmierst nicht wirklich so, oder? 😃

    Meinst du cat oder den Schönen Pointer-Aufruf 😃 Für Programme unter 10 Zeilen tuts cat doch ausgezeichnet und wie kann man schöner einen segv provozieren 😉

    Vielleicht noch

    int main() {
       return *((char *)0);
    }
    

    😃



  • Hi Leute,
    irgendwie kann man das Problem mit dem Segmentation fault umgehen, und zwar indem ich einfach ein cout-anweisung vorsetze. In dem Code-Beispiel von TriPhoenix hat das aber nicht funktioniert! Fragt mich aber nicht genau warum das so ist, ich kann nur vermuten, dass es was mit dem timing zu tun hat und er vielleicht nur ne kleine pause zwischendurch braucht! siehe http://lists.suse.com/archive/suse-linux-e/1999-Jun/0262.html.
    Meinen RAM habe ich auch schon ausgetauscht und diverse Parameter im BIOS habe ich auch schon alles durchprobiert, hat aber alles nichts geholfen!
    Also, ich finde, dass das eine sehr seltsame bzw. ungewöhnliche Geschichte ist!

    Bis dann.



  • Ringostarr schrieb:

    Hi Leute,
    irgendwie kann man das Problem mit dem Segmentation fault umgehen, und zwar indem ich einfach ein cout-anweisung vorsetze.

    Darf man die "problematische" Stelle mal sehen?

    In dem Code-Beispiel von TriPhoenix hat das aber nicht funktioniert! Fragt mich aber nicht genau warum das so ist

    Klar, mein Code provoziert einen ungüötigen SPeicherzugriff, da kann nur ein SIGSEGV rauskommen. Dein Code tuts wahrscheinlich nu unte ungünstigen Umständen. Irgendwas mit Threads oder so dabei? Irgendeine Fehelrprüfung nicht gemacht?

    http://lists.suse.com/archive/suse-linux-e/1999-Jun/0262.html.
    Meinen RAM habe ich auch schon ausgetauscht und diverse Parameter im BIOS habe ich auch schon alles durchprobiert, hat aber alles nichts geholfen!
    Also, ich finde, dass das eine sehr seltsame bzw. ungewöhnliche Geschichte ist!

    Jup, der Artikel bezieht sich vor allem auch auf SIGSEGV beim kompilieren. Ich denke shcon dass das Problem bei dir softwareseitig liegt.



  • Du bist anscheinend ziemlich verwirrt, was ein Segfault ist. Das bedeutet *nichts anderes*, als dass ein Programm einen unerlaubten Zugriff auf eine Speicheradresse durchgeführt hat, auf die es nicht zugreifen darf. Wie man das künstlich produzieren kann, siehe Beispielprogramm TriPhoenix hier in diesem Thread. Mit anderen Worten, ein Segmentation Fault deutet eigentlich immer auf ein fehlerhaftes Programm hin.

    Der Link den du ausgegraben hast, bezieht sich auf einen spezifischen Zusammenhang: Beim Kernelcompilieren baut der GCC sehr große komplizierte Datenstrukturen -- für syntaktische und semantische Informationen -- im Speicher auf, die sehr viele Pointer enthalten. Wenn jetzt der Arbeitsspeicher irgendwo Fehler hat, dann zeigt ganz schnell mal einer dieser Pointer auf eine verbotene Adresse, so dass der Compiler mit einem SIGSEGV abstürzt, wenn er beim Durchlaufen der Datenstrukturen diesem Pointer folgt. Da man im Allgemeinen annimmt, dass der Compiler in der Hinsicht fehlerfrei ist, muss das Problem an der Hardware liegen.

    Ausserhalb davon, insbesondere wenn du eigene Programme ausprobierst, ist das schlicht und einfach ein Programmierfehler, den du nicht durch neuen RAM oder Bios-Basteleien ausmerzen kannst.



  • Jo, das Code-beispiel kannste haben, aber erst heute abend, ich muss jetzt erstmal wieder zur Arbeit 😋
    Bis denn!



  • So, ich geb mal die Codestelle an! Der Programmcode ist übrigens der gleiche, wie beim folgenden --->
    http://www.c-plusplus.net/forum/viewtopic.php?t=49077&highlight= Forumsbeitrag:

    ...
    int main(int argc, char **argv)
    {
      struct arguments arguments;
      /* Vorbelegen */
      char *outputfile;
      cout << "schreibt er noch hin!";
      strncpy(outputfile, "-", sizeof(outputfile));
      cout << "schreibt er nicht mehr hin!";
      arguments.silent=0;
      arguments.version=0;
      arguments.html=0;
      arguments.xml=0;
      arguments.output_file=outputfile;
      argp_parse(&argp, argc, argv, 0, 0, &arguments);
      ...
    

    Also, es scheint wohl ganz so, als wenn die Zeile mit dem strncpy-Befehl probleme macht. Ich nehme mal ganz stark an, das ich mit dem Zeiger von outputfile was falsch mache???
    Die sache ist nur folgende: wenn ich die erste cout-Zeile auskommentiere/lösche dann gibts den SegFault, wenn ich dagegen, die nur die zweite cout-Zeile auskommentiere und die erste drinlasse, dann gibts keinen SegFault.
    So, nun kann ich folgendes machen. Ich lösche die strncpy-Zeile komplett raus und ersetze die vorletzte Zeile durch folgende:

    arguments.output_file="-";
    

    Dieses wollte ich aber bewusst umgehen, weil mir KDevelop sonst eine 'deprecated conversion from string constant to `char*'-Warnung ausgibt.
    Ich hoffe das reicht erstmal an Erläuterung 😉

    Ein frage an Bashar: Warum bist du eigentlich noch kein Moderator? Du scheinst ja einiges zu Wissen und ich hab dich hier auch schön öfters gesehen!



  • Da haben wirs ja. outputfile ist nicht initialisiert. Damit zeigt er unkontrolliert irgendwo in die Botanik, ausserhalb deiner Kontrolle. Mit strncpy kopierst du jetzt einen ganzen Haufen Zeichen an die Stelle, wo outputfile hinzeigt. Dass das nicht gut ist, sollte sich von selbst verstehen.
    Wenn dein Programm an der Stelle abstürzt, heißt das nur, dass outputfile zufälligerweise an eine "verbotene" Stelle gezeigt hat.


Anmelden zum Antworten