mysteriöser Segmentation Fault



  • Hi everyone

    Folgendes Problem: in meiner main()-Methode kopiere ich alle Argumente in einen Vektor und geben den an meine eigentlich (public static) main-Methode in meiner Hauptklasse weiter.

    Das mache ich in jedem Programm so und es hat noch nie Probleme verursacht. Aber in diesem Fall erhalte ich nach der (korrekten) Ausführung des ganzen Programms einen Segmentation Fault. Das ist darum lästig, weil ich das Programm als via CGI aufrufen wollte und mein Webserver die Ausgabe nicht anzeigt, wenn ein Fehler aufgetreten ist.

    Der Code dazu sieht wie folgt aus:

    #include "EwbConfig.h"
    #include <iostream>
    
    using namespace ewbconfig;
    using namespace std;
    
    int main(int argc, const char *argv[]) {
        vector<string> args(argc);
        copy(argv, &argv[argc], args.begin());
    
        int i = EwbConfig::main(args);
        cout << "everything destructed" << endl;
        return i;
    }
    

    Erst dachte ich, es könne sich nur um Fehler beim Destruieren meiner Objekte handeln, deshalb habe ich den cout ganz am Ende eingefügt (der noch vor dem SegFault angezeigt wird). Da es sich um eine static-Methode handelt wird nach dem cout sicher keine meiner Klassen mehr destruiert, sondern nur noch der vector. Anschliessend wird nur noch i zurückgegeben (=0, EwbConfig::main() gibt immer 0 zurück).

    Wo um Himmels Willen kann da also noch ein Segmentation Fault entstehen? Man beachte, dass args als const-Reference übergeben wird.

    Ich habe via gdb das entstandene core-File angesehen und folgenden backtrace erhalten:

    GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-23)
    Copyright 2004 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 "--host=i686-pc-linux-gnu --target=armv5teb-montavista-linuxeabi"...
    Core was generated by `./ewbconfig.exe'.
    Program terminated with signal 11, Segmentation fault.
    Reading symbols from /usr/local/xscale_be/target/lib/libewbmeter.so...done.
    Loaded symbols for /usr/local/xscale_be/target/lib/libewbmeter.so
    Reading symbols from /usr/local/xscale_be/target/usr/lib/libstdc++.so.6...done.
    Loaded symbols for /usr/local/xscale_be/target/usr/lib/libstdc++.so.6
    Reading symbols from /usr/local/xscale_be/target/lib/libm.so.6...done.
    Loaded symbols for /usr/local/xscale_be/target/lib/libm.so.6
    Reading symbols from /usr/local/xscale_be/target/lib/libgcc_s.so.1...done.
    Loaded symbols for /usr/local/xscale_be/target/lib/libgcc_s.so.1
    Reading symbols from /usr/local/xscale_be/target/lib/libc.so.6...done.
    Loaded symbols for /usr/local/xscale_be/target/lib/libc.so.6
    Reading symbols from /usr/local/xscale_be/target/lib/libpthread.so.0...done.
    Loaded symbols for /usr/local/xscale_be/target/lib/libpthread.so.0
    Reading symbols from /usr/local/xscale_be/target/lib/ld-linux.so.3...done.
    Loaded symbols for /usr/local/xscale_be/target/lib/ld-linux.so.3
    #0  0x40409580 in std::_Rb_tree_rebalance_for_erase () from /usr/local/xscale_be/target/usr/lib/libstdc++.so.6
    (gdb) backtrace
    #0  0x40409580 in std::_Rb_tree_rebalance_for_erase () from /usr/local/xscale_be/target/usr/lib/libstdc++.so.6
    #1  0x4062d1c4 in nullserv () from /usr/local/xscale_be/target/lib/libc.so.6
    #2  0x4062d1c4 in nullserv () from /usr/local/xscale_be/target/lib/libc.so.6
    

    Besten Dank schon im Voraus für eure Hilfe & Greeetz
    Kessi



  • Dein Vector ist zu klein, nämlich leer. Entweder Du verwendest vor dem Einfügen 'resize' oder beim Kopieren einen 'back_inserter'. Außerdem kopierst Du ein Element zuwenig. Besser:

    copy(argv, argv + argc, vec.begin());
    


  • Sorry, verlesen und GDB-Trace ignoriert. Also, da der Fehler in einer Rot-Schwarz-Baum-Methode auftritt würde ich vermuten, dass er irgendwo in std::map ausgelöst wird. Mit Deinem Code sollte das nichts zu tun haben, abgesehen davon, dass Du nach wie vor ein Element zuwenig kopierst. Vielleicht steht dort ein erwarteter Parameter?

    Wäre dann aber ein böses Programm. 😉



  • Hi again

    Danke für die Antworten 🙂 .

    copy(argv, &argv[argc], args.begin());
    

    entspricht in seiner Funktion allerdings genau

    copy(argv, argv + argc, vec.begin());
    

    &argv[argc] zeigt ja, ebenso wie argv + argc, genau hinter das letzte Element. Nur dass ich mir bei ersterem keine Gedanken um sizeof(char 😉 machen muss 🙂 .

    Andererseits fällt mir auf, dass ich bei ersterem evtl. erst auf einen nicht alloziierten Speicher zugreife, ehe ich einen Pointer daraus mache:

    &(argv[argc])
    

    Wenn das ein Bereich ist, in dem ich nicht lesen darf, schmiert mein Programm schon mal per se ab. Muss ich gleich korrigieren 🙂 .

    Was das eigentliche Problem mit dem Segmentation Fault angeht: Mein Programm verwendet eine shared library, bei der zum Teil gewisse Objektdateien bereits in der Library waren und trotzdem noch beim Linken des Programms statisch gelinkt wurden.

    Während das für minGW kein Problem darstellt, war das Resultat bei cygwin halt ein Crash nach der eigentlichen Programmausführung. Naja.

    Diese Unschönheit ist jetzt jedenfalls behoben und es scheint vorerst zu funktionieren.

    Thx again & greeetz
    Kessi



  • Hi Kessi,

    vorab ne Entschuldigung, irgendwie war ich beim Beantworten ein wenig von der Rolle und habe im großen und ganzen nur Mist geschrieben.

    KessiMC schrieb:

    copy(argv, &argv[argc], args.begin());
    

    entspricht in seiner Funktion allerdings genau

    copy(argv, argv + argc, vec.begin());
    

    Du hast natürlich recht.

    Andererseits fällt mir auf, dass ich bei ersterem evtl. erst auf einen nicht alloziierten Speicher zugreife, ehe ich einen Pointer daraus mache:

    Richtig, das ist in der Tat undefiniertes Verhalten, und bringt zumindest auf einem mir bekannten Compiler (Visual Studio) manchmal einen Absturz, bzw. wird vom Debugger als fehlerhafter Speicherzugriff erkannt.


  • Mod

    KessiMC schrieb:

    Andererseits fällt mir auf, dass ich bei ersterem evtl. erst auf einen nicht alloziierten Speicher zugreife, ehe ich einen Pointer daraus mache:

    &(argv[argc])
    

    Wenn das ein Bereich ist, in dem ich nicht lesen darf, schmiert mein Programm schon mal per se ab. Muss ich gleich korrigieren 🙂 .

    Formal wäre es gegenwärtig undefiniert, unmittelbar hinter dem letzten Element eines Arrays zuzugreifen, um einen Zeiger darauf zu bilden. Es besteht allerdings Einigkeit im beiden Standardkomitees (C und C++), dass diese Art des Zugriffs erlaubt sein soll, die nächsten Standards werden das reflektieren; außer vielleicht auf exotischen Plattformen oder mit paranoiden Validierungstools dürfte auch heute kein praktisches Problem bestehen. Im Übrigen besteht das Problem hier sowieso nicht: das Array, in das argv zeigt, enthält tatsächlich argc+1 Zeiger, der Letzte zeigt auf einen String der Länge 0.


Anmelden zum Antworten