[SOLVED] Abzählreim Programm produziert SIGSEGV, aber warum?



  • Ich versuche gerade, ein Algorytmus Beispiel aus einer Vorlesung (dor wird JAVA verwendet) in C++ umzusetzen. Hoffe ich bin in der richtigen Rubrik gelandet.

    Der Code wird auch anstandslos copiliert, aber stürzt bei der ausführung ab.
    Der Debugger wirft mir bei Zeile 14 einen SIGSEGV aus.

    Frage: warum?

    Vieleicht sehe ich den Fehler vor laute code wieder mal nicht also zerreist mich nicht gleich :). Hier mal das Programm.

    #include <iostream>
    
    int main() // int argc, char* argv[])
    {
        int index, childs, nouns;
    
        std::cout << "Gib die Anzahl der Kinder ein die am Abzaehlreim teilnehmen : ";
        std::cin >> childs;
        std::cin.get();
        std::cout << "Gib die Anzahl der Silben an die verwendet werden sollen : ";
        std::cin >> nouns;
        std::cin.get();
    
        std::cout << std::endl << "Es nehmen " << childs << " Kinder teil und es werden " << nouns << " Silben verwendet" << std::endl << std::endl;
    
        int indizes[childs];
    
        for(int i = 0; i < childs; i++)
        {
            indizes[i] = i + 1 % childs;
        }
    
        index = childs - 1;
    
        while(index != indizes[index])
        {
            for(int i = 0; i < nouns - 1; i++)
            {
                index = indizes[index];
            }
            std::cout << "Raus ist " << indizes[index] << std::endl;
            indizes[index] = indizes[indizes[index]];
        }
    
        std::cout << std::endl << "Uebrig bleibt " << index << std::endl << std::endl;
    
        std::cout << "Druecke \'Return\' zum beenden." << std::endl;
        std::cin.get();
        std::cin.get();
    
        return 0;
    }
    

    Compier Ausgabe:
    -------------- Build: Debug in Counting_Out_Rhyme (compiler: GNU GCC Compiler)---------------

    mingw32-g++.exe -Wall -fexceptions -g -Wfloat-equal -Winline -Wunreachable-code -Wswitch-enum -Wswitch-default -Weffc++ -std=c++0x -Wextra -Wall -g -c "D:\Eigene Dokumente\CodeBlocls\Counting_Out_Rhyme\Counting_Out_Rhyme.cpp" -o Objects\Counting_Out_Rhyme.o
    mingw32-g++.exe -o Debug\Counting_Out_Rhyme.exe Objects\Counting_Out_Rhyme.o -static-libgcc -static-libstdc++
    Output size is 1.26 MB
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 0 warnings (0 minutes, 0 seconds)

    Debugger Ausgabe:
    Registered new type: wxString
    Registered new type: STL String
    Registered new type: STL Vector
    Setting breakpoints
    Debugger name and version: GNU gdb 6.8
    Child process PID: 14564
    Program received signal SIGSEGV, Segmentation fault.
    At D:\Eigene Dokumente\CodeBlocls\Counting_Out_Rhyme\Counting_Out_Rhyme.cpp:14



  • Du hast doch bestimmt schon mit dem Debugger geprüft, welche Zeile für den Fehler verantwortlich ist?



  • Compilerwarnungen höher drehen. Bei mir heisst es z.B.:

    test.cc:16:23: warning: ISO C++ forbids variable length array ‘indizes’ [-Wvla]
    

    Schau noch mal in Deine C++ Unterlagen, wie das ist mit dynamischen Arrays, bzw. deren Alternative std::vector<> .



  • int indizes[childs];
    

    Dieses hier solltest du mal versuchen zu ändern in

    int *indizes = new int[ childs ];
    

    Um Speicherlecks zu vermeiden solltest du dann, wenn du das Array nicht mehr brauchst, den Speicher wieder freigeben mit

    delete [] indizes;
    

    Anmerkung: Der Plural von "Child" ist "Children" 😉



  • i + 1 % childs

    Das liest der Compiler als
    i + (1 % childs)

    du willst aber vermutlich

    (i % childs)+1



  • It0101 schrieb:

    int indizes[childs];
    

    Dieses hier solltest du mal versuchen zu ändern in

    int *indizes = new int[ childs ];
    

    wenn schon ändern, dann bitte in std::vector. Ich sehe keinen Grund, hier new/delete reinzubringen.



  • Ah: Moment... die Compilerausgaben waren vorher nicht da, oder?!
    Den richtigen Code posten.... gelesen, was? 🙂

    Nimm noch den -pedantic Schalter dazu!



  • Furble Wurble schrieb:

    Compilerwarnungen höher drehen. Bei mir heisst es z.B.:

    test.cc:16:23: warning: ISO C++ forbids variable length array ‘indizes’ [-Wvla]
    

    Schau noch mal in Deine C++ Unterlagen, wie das ist mit dynamischen Arrays, bzw. deren Alternative std::vector<> .

    It0101 schrieb:

    int indizes[childs];
    

    Dieses hier solltest du mal versuchen zu ändern in

    int *indizes = new int[ childs ];
    

    Um Speicherlecks zu vermeiden solltest du dann, wenn du das Array nicht mehr brauchst, den Speicher wieder freigeben mit

    delete [] indizes;
    

    Anmerkung: Der Plural von "Child" ist "Children" 😉

    Irrelevant weil der GCC VLA kennt.



  • Shade Of Mine schrieb:

    i + 1 % childs

    Das liest der Compiler als
    i + (1 % childs)

    du willst aber vermutlich

    (i % childs)+1

    Nicht ganz, er will (i+1) % childs. Und dann klappt das ganze auch...



  • Skym0sh0 schrieb:

    Shade Of Mine schrieb:

    i + 1 % childs

    Das liest der Compiler als
    i + (1 % childs)

    du willst aber vermutlich

    (i % childs)+1

    Nicht ganz, er will (i+1) % childs. Und dann klappt das ganze auch...

    Exakt das wars, der Tafelanschrieb war nicht korrekt, habs eben nochmal im Skript nachgeschaut und da wars dann.


  • Mod

    Videonauth schrieb:

    Exakt das wars, der Tafelanschrieb war nicht korrekt, habs eben nochmal im Skript nachgeschaut und da wars dann.

    Im sinne der Aufgabenstellung solltest du aber trotzdem noch Zeile 16 in std::vector ändern, da VLAs bloß eine Erweiterung deines Compilers sind, kein Standard-C++. Das weiß (hoffentlich!) auch dein Lehrer.

    Ansonsten könnte man noch viele Kleinigkeiten stilistisch verbessern, aber es sind keine weiteren "echte" Fehler mehr drin.



  • Nachtrag dazu:
    Damit es bei mir kompiliert (Visual Studio 2012) habe ich (wie SeppJ jetzt schon gesagt hat) diese Zeile

    int indizes[childs];
    

    in diese geändert:

    std::vector<int> indizes(childs);
    

    Macht das gleiche und ist besser und sicherer.



  • Videonauth schrieb:

    Exakt das wars, der Tafelanschrieb war nicht korrekt, habs eben nochmal im Skript nachgeschaut und da wars dann.

    Auch klar warum das so sein muss?



  • Shade Of Mine schrieb:

    Videonauth schrieb:

    Exakt das wars, der Tafelanschrieb war nicht korrekt, habs eben nochmal im Skript nachgeschaut und da wars dann.

    Auch klar warum das so sein muss?

    Ist mir noch nicht ganz klar, da lese ich grade darüber und arbeite es auf dem Papier auf.



  • Videonauth schrieb:

    Shade Of Mine schrieb:

    Videonauth schrieb:

    Exakt das wars, der Tafelanschrieb war nicht korrekt, habs eben nochmal im Skript nachgeschaut und da wars dann.

    Auch klar warum das so sein muss?

    Ist mir noch nicht ganz klar, da lese ich grade darüber und arbeite es auf dem Papier auf.

    % liefert ja den Rest einer Division.

    Also
    5%3 == 1 mal, 2 Rest
    Sprich: 2 ist das ergebnis

    Das bedeutet aber auch, dass man mit % einen maxmimal Wert bestimmen kann:
    n%m ist 0 bis (m-1)
    Denn wenn der Rest gleich m wäre - dann würde m ja noch einmal mehr rein passen.

    (i % childs)+1
    oder auch
    (i+1) % childs

    ich bin mir nicht sicher was von beiden das gewünschte ist, aber ich tippe mittlerweile eher auf das 2.

    Das ergebnis vom 1. ist 1 bis childs
    Das ergebnis vom 2. ist 0 bis childs-1



  • Also konkret:

    (i+1)%childs

    Sei gegeben 5 Kinder, ergeben dich folgende Indizes

    Array[0] = (0+1)%5 = 0 Rest 1 = 1
    Array[1] = (1+1)%5 = 0 Rest 2 = 2
    Array[2] = (2+1)%5 = 0 Rest 3 = 3
    Array[3] = (3+1)%5 = 0 Rest 4 = 4
    Array[4] = (4+1)%5 = 1 Rest 0 = 0

    Wenn ich das nun richtig verstanden habe.



  • Videonauth schrieb:

    Wenn ich das nun richtig verstanden habe.

    👍



  • Und genau diese Ergebnisse nutzt du später als Index für dein Array um Kinder zu eliminieren, wenn es keine Silben mehr zum Sprechen gibt.

    Der Knackpunkt ist, die nutzt eben diese Ergebnisse später als Index, daher muss es die 2. von Shade-of-Mine's Lösungen sein, die erste gibt dir wie du gemerkt hast Fehler beim Arrayzugriff (Out-Of-Bounds 'n' shit)


Anmelden zum Antworten