Programmabsturz aufgrund SIGSEGV



  • Guten Tag zusammen,

    ich habe eine Funktion geschrieben, die Hindernisse erkennen soll. Dazu nutze ich einen entsprechenden Sensor. Im Allgemeinen möchte ich jedoch mehr als ein Hindernis erkennen. Dies Funktioniert bisher auch problemlos.

    Da sich jedoch eine gewisse Varianz bei der Position eines Hindernisses ergibt, möchte ich 10 Scans durchführen und die Position dann mitteln.

    Meine Funktion sieht so aus:

    vector<vector<double>> statische_hinderniserkennung(){
        vector<vector<vector<double>>> speicher1;
        vector<double> speicher2;
        for(int i=0; i<10; i++){
            starte_messung();
            erzeuge_abstaende_und_winkel_im_zulBer();
            erzeuge_rohdaten_im_zulBer();
            erzeuge_hindernisse_gesamt();
            modelliere_hindernisse(hindernisse_gesamt);
            speicher1.push_back(modellierte_hindernisse);
        }
        //unsigned k =0;
        for(unsigned k=0; k<modellierte_hindernisse.size(); k++){
          double x=0;
          double y=0;
          double r=0;
          double zeit=0;
          for(unsigned j=0; j<speicher1.size();j++){
              x= x + speicher1[j][k][0];
              y= y + speicher1[j][k][1];
              r= r + speicher1[j][k][2];
          }
          x=x/10;
          y=y/10;
          r=r/10;
          zeit=speicher1.back()[k].back();
          speicher2.push_back(x);
          speicher2.push_back(y);
          speicher2.push_back(r);
          speicher2.push_back(zeit);
          statische_hindernisse.push_back(speicher2);
          speicher2.resize(0);
        }
        return statische_hindernisse;
    }
    

    Leider stürzt so das Programm immer ab, da es vom Betriebssystem das Signal SIGSEGV bekommt. Bisher weiß ich nicht viel über dieses Signal, außer das es meist was mit unrechtmäßigem Speicherzugriff zu tun hat.

    Wenn ich k jedoch per Hand hochzähle kann das Programm problemlos durchlaufen und gibt mir auch das richtige an.

    Meine Main sieht so aus und macht nichts, außer mir die gemittelten Hindernispositionen auszugeben:

    statische_hinderniserkennung();
        for(unsigned i=0; i<statische_hindernisse.size();i++){
            for(unsigned j=0;j<statische_hindernisse[i].size();j++){
                cout << statische_hindernisse[i][j] << "   ";
            }
            cout << endl;
        }
    

    Es wäre toll, wenn mir jemand sagen kann, warum bei dieser for-Schleife mein Programm abstürzt und warum es klappt, wenn ich k=0, k=1,... setze.



  • zwei Sachen:

    1. könntest du dich mal mit structs beschäftigen

    speicher2.push_back(x);
    speicher2.push_back(y);
    speicher2.push_back(r);
    speicher2.push_back(zeit);
    

    schreit ja gerade zu nach

    struct daten
    {
      //mit ctor
      double x;
      double y;
      double zeit;
    };
    
    std::vector<daten> die_daten;
    

    um die komplexität mal ein wenig zu reduzieren

    2. dein Absturz kommt sehr wahrscheinlich von

    statische_hindernisse[i][j]

    weil du auf irgendwas zugreifst was nicht da ist

    am einfachsten mal ein

    #include <cassert>

    und vor dem

    cout << statische_hindernisse[i][j] << "   ";
    

    assert(i < statische_hindernisse.size());
    assert(j < statische_hindernisse[i].size());

    einbauen



  • Dann schreibst du deine Zugriffe mal so

    speicher1.at(j).at(k).at(0);
    

    und stellst fest, welchen vector du nicht in der richtigen grösse lieferst.



  • Ich habe eure Tipps angewandt und bekomme momentan folgende Ausgabe:

    terminate called after throwing an instance of 'std::out_of_range'
    what(): vector::_M_range_check

    Ich verstehe jetzt aber ehrlich gesagt immer noch nicht, wo genau das Problem ist..

    Structs wären wohl echt ne gute Idee, das steuer ich nach!

    Jetzt schmeißt mir mein Betriebssystem übrigens ein SIGABRT Signal..



  • Ich verstehe jetzt aber ehrlich gesagt immer noch nicht, wo genau das Problem ist..

    die i und/oder j sind nicht in deinem vector - du versucht mehr zu lesen als da ist - also wird er nicht richtig befuellt oder deine Ausgabe ist falsch


  • Mod

    Du greifst halt fröhlich auf leere Vectoren zu. Das ist ja auch kein Wunder, denn wenn man mehr als zwei Verschachtelungsebenen (Puristen würden sogar auf nur als einer bestehen!) innerhalb eines logischen Abschnitts hat, dann macht man sich nur selbst das Leben schwer und provoziert unnötige Fehler, weil man den Durchblick verliert. Die schon erwähnte Nicht-Benutzung von structs oder anderen Datenstrukturen zum Zusammenfassen von zusammengehörigen Daten verschärft das Problem nochmals erheblich.

    Von der Art deiner Bezeichner her (speicher? Ist das wirklich was ein Vector für dich ist?) und der Art, wie du sie verschachtelst (siehe Kommentar oben), vermute ich stark, dass dir nicht so ganz klar ist, was ein verschachtelter Vector überhaupt für eine Struktur ist. Es ist kein 2D-Array! Jeder der inneren Vectoren ist vollkommen unabhängig von den anderen und hat seinen eigenen Speicherbereich und seine eigene Größe. Oder hier eben auch keine Größe, denn soweit ich das sehr, sind die bei dir alle leer; vermutlich weil du denkst, dass die sich irgendwie von alleine füllen.



  • aber wieso sind die Vektoren denn leer?
    ich scanne zwei objekte, d.h. "modellierte_hindernisse" hat zwei Einträge.
    "speicher1" hat zehn Einträge, wobei jeder Eintrag ein Vektor mit je zwei Einträgen ist...

    Wenn ich nun k=0 setze und die Funktion so schreibe:

    vector<vector<double>> statische_hinderniserkennung(){
        vector<vector<vector<double>>> speicher1;
        vector<double> speicher2;
        for(int i=0; i<10; i++){
            starte_messung();
            erzeuge_abstaende_und_winkel_im_zulBer();
            erzeuge_rohdaten_im_zulBer();
            erzeuge_hindernisse_gesamt();
            modelliere_hindernisse(hindernisse_gesamt);
            speicher1.push_back(modellierte_hindernisse);
        }
        unsigned k =0;
        //for(unsigned k=0; k<modellierte_hindernisse.size(); k++){
          double x=0;
          double y=0;
          double r=0;
          double zeit=0;
          for(unsigned j=0; j<speicher1.size();j++){
              x= x + speicher1.at(j).at(k).at(0);
              y= y + speicher1.at(j).at(k).at(1);
              r= r + speicher1.at(j).at(k).at(2);
          }
          x=x/10;
          y=y/10;
          r=r/10;
          zeit=speicher1.back().at(k).back();
          speicher2.push_back(x);
          speicher2.push_back(y);
          speicher2.push_back(r);
          speicher2.push_back(zeit);
          statische_hindernisse.push_back(speicher2);
          speicher2.resize(0);
        //}
        return statische_hindernisse;
    }
    

    bekomme ich die richtigen Daten für das erste Objekt ausgegeben, für k=1 bekomme ich das andere Objekt korrekt ausgegeben.

    Was mache ich denn da mit der For-Schleife falsch?
    "modellierte_hindernisse.size()" ist doch gleich zwei, sodass doch eigentlich nicht auf leere Vektoren zugegriffen wird?

    Bin leider nicht so erfahren mit C++ aber das die Vektoren leer sein sollen ergibt für mich noch keinen sinn...

    übrigens: vektoren sind nicht nur speicher für mich, aber mir viel kein besserer name ein. Desweiteren nutze ich ja extra Vektoren, weil sie eben unabhängig voneinander sind..



  • käsebrot95 schrieb:

    Was mache ich denn da mit der For-Schleife falsch?
    "modellierte_hindernisse.size()" ist doch gleich zwei, sodass doch eigentlich nicht auf leere Vektoren zugegriffen wird?

    Benutze einen Debugger! Dann weißt du, welches at die Exception wirft.


  • Mod

    käsebrot95 schrieb:

    aber wieso sind die Vektoren denn leer?
    ich scanne zwei objekte, d.h. "modellierte_hindernisse" hat zwei Einträge.
    "speicher1" hat zehn Einträge, wobei jeder Eintrag ein Vektor mit je zwei Einträgen ist...

    Mag sein, dass sie nicht ganz leer sind, sondern nur zu kurz. Kommt aber aufs gleiche raus: Deine Befüllung macht offensichtlich etwas anderes als du denkst, denn sonst würde schließlich der spätere Zugriff funktionieren. Da du uns nicht konkret zeigst, wie die Befüllung abläuft, kann man nicht genau sagen, was da schief läuft. Erfahrungsgemäß sind das bei mehrfach verschachtelten Vectoren immer Probleme mit leeren inneren Vectoren. Ich würde auch trotz deiner Beteuerungen immer noch da drauf wetten, dass dies auch hier der Fall ist. Du hast hier schließlich drei Schachtelebenen, beschreibst aber nur, was du auf zwei von diesen tust.

    Wenn du dein Programm mal mit einem Debugger ausführst, kannst du den Inhalt deiner Datenstrukturen bei jedem Programmschritt kontrollieren und mit deinen Vorstellungen vergleichen. Du kannst ja mal gucken, ob nach dem Füllen tatsächlich das drin ist, was du dachtest.
    Und insbesondere kannst du mit dem Debugger auch sehen, welche Stelle genau den Absturz verursacht, auf welchen Elementindex dort zugegriffen wird und wie viele Elemente es tatsächlich gibt.



  • ok danke dir! habe herausgefunden, dass mein k zu hoch läuft. Bei zwei objekten klappt alles für k=0 und k=1, aber die schleife setzt dann k=2 und dann greife ich auf ungültige Elemente zu. Hier folgt dann der Absturz..

    "modellierte_hindernisse.size()" ist gleich 4512... dann ist da irgendwo was schief gelaufen..



  • Structs wären wohl echt ne gute Idee, das steuer ich nach!

    mach es jetzt!!!

    dann werden deine möglichen Problemstelle gleich viel weniger
    und dann sieht du auch besser wo dein Problem herkommt


Log in to reply