glibc detected malloc(): memory corruption



  • Guten Abend,

    ich bekomme bei der Ausführung von meinem Code den Fehler:

    *** glibc detected *** /home/phost/NetBeansProjects/MediaServer/dist/Debug/GNU-Linux-x86/mediaserver: malloc(): memory corruption: 0x08b29728 ***
    

    Ich habe auch schon ein wenig auf eigene Faust gesucht.
    Was ich herausgefunden habe ist das es (offensichtlich) ein Speicher Problem ist. Allerdings waren sämtliche Ergebnisse die ich gefunden bezüglich dem "invalid pointer"-Fehler, was ich ja nicht habe.

    Was konkret bei mir passieren soll ist eine rekursive Funktion die ein Verzeichnis inkl. Unterverzeichnis ausliest.

    void directoryScanner::scanDir(const char* _dir) {
        printf("Scanning Directory %s\n", _dir);
        DIR *dir_handle;
        struct dirent *pointer;
        struct stat attributes;
        if ((dir_handle = opendir(_dir)) != NULL) {
            while ((pointer = readdir(dir_handle)) != NULL) {
                const char* file = (*pointer).d_name;
                if (strcmp(file, ".") == 0 || strcmp(file, "..") == 0) {
                    continue;
                }
                char* temp = new char(strlen(_dir) + strlen(file) + 1);
                strcpy(temp, _dir);
                strcat(temp, "/");
                strcat(temp, file);
                stat(temp, &attributes);
                if (attributes.st_mode & S_IFDIR) {
                    printf("Found Directory: %s\n", temp);
                    this->scanDir(temp);
                } else {
                    printf("Found File: %s\n", temp);
                }
                fflush(stdout);
            }
        }
        closedir(dir_handle);
    }
    

    Dazu folgende Ausgabe in der Konsole:

    Scanning Directory /var/media/music
    Found Directory: /var/media/music/Blink182
    Scanning Directory /var/media/music/Blink182
    *** glibc detected *** /home/phost/NetBeansProjects/MediaServer/dist/Debug/GNU-Linux-x86/mediaserver: malloc(): memory corruption: 0x08b29728 ***
    

    Wenn ich im Code

    this->scanDir(temp);
    

    auskommentiere läuft es auch nur bis zum ersten Ergebnis durch.

    Wenn der zu durchsuchende Ordner hingegen nur einen Ordner beinhaltet funktioniert es ohne Probleme.

    Daher jetzt also meine Frage:
    Wodurch kann der Fehler ausgelöst werden? Ist es sogar möglich das mein Speicher irgendwie wirklich kaputt ist, also hardware-seitig?
    Als ich das ganze im Debug-Modus durchlaufen habe habe ich allerdings gesehen das zB mein RAM noch nicht ausgelastet ist, daran sollte es also nicht liegen..
    Falls jemand mir einen Wink in Form weiterführendem Lesestoff geben kann wäre ich auch schon dankbar 😃
    Es gibt zu der Fehlermeldung auch noch einen mehrere Zeilen langen Backtrace den ich jetzt der Übersichtlichkeit halber noch außen vor gelassen habe.

    'n Gruß



  • Mir fällt

    char* temp = new char(strlen(_dir) + strlen(file) + 1);
    

    auf. Ist da die Nullterminierung dabei?
    edit: Und was machen die runden Klammern da?



  • *kopf -> tisch* (mehrmals)

    Alles klar..
    Die runden Klammern müssen natürlich eckige sein.. oh man..
    Das war's schon 😃

    Aber ich hake nochmal nach: Was genau meinst du mit "Nullterminierung"?
    Das der char nicht "null" ist, ist gegeben. Da selbst wenn _dir und file die Länge null haben ja noch die 1 da steht, somit ist temp mind char[1].
    Falls es das ist was du meintest.



  • phost schrieb:

    *kopf -> tisch* (mehrmals)

    Alles klar..
    Die runden Klammern müssen natürlich eckige sein.. oh man..
    Das war's schon 😃

    Aber ich hake nochmal nach: Was genau meinst du mit "Nullterminierung"?
    Das der char nicht "null" ist, ist gegeben. Da selbst wenn _dir und file die Länge null haben ja noch die 1 da steht, somit ist temp mind char[1].
    Falls es das ist was du meintest.

    Ich male Dir ein Bildchen. 🤡
    *vorher Kissen auf den Tisch leg*

    new char(strlen(_dir) + 1 + strlen(file) + 1);
                       ^    ^            ^     ^
    strcpy(temp, _dir);|    |            |     |
                            |            |     |
    strcat(temp, "/");------+            |     |
                                         |     |
    strcat(temp, file);------------------+     |
                                               |
    //abschließende '\0'-----------------------+
    


  • Haha danke fürs Kissen, aber Strafe muss sein 😃

    Okay mit dem Bildchen macht das Sinn, aber unter der \0 kann ich mir jetzt nichts anderes vorstellen als eine art abschließendes Byte? Und wird dieses immer automatisch eingefügt? Oder wird das erst durch strcat automatisch eingefügt??





  • Vielen Dank! 🙂



  • warum benutzt du nicht std::string?



  • So wie ich das gesehen habe wollen fast alle Funktionen nen const char* als Parameter haben.
    Und da müsste ich dann ja erst in string umwandeln und später das ganze rückgängig machen?





  • naja diese Funktion gibt ja auch einen const char* zurück, das ist ja das was ich meinte.



  • Du speicherst alles in std::string, wenn eine Funktion einen const char* haben will, dann gibst du ihr die Rückgabe von c_str(). Mehr brauchst du eigentlich nicht umwandeln.

    Edit: In die andere Richtung gehts übrigens mit dem Konstruktor von std::string.



  • Nunja das ist mir natürlich klar.

    Aber da ja letzten Endes eh so gut wie jede Funktion einen const char* verlangt kann ich das alles ja auch direkt als const char* deklarieren und entsprechend damit arbeiten.

    Einziger Vorteil bei strings ist natürlich das man mit denen deutlich einfacher rumhantieren kann in den meisten Fällen. Aber um das alles an eine Funktion zu übergeben muss man einen String dann eben doch wieder in const char* umwandeln.



  • phost schrieb:

    Einziger Vorteil bei strings ist natürlich das man mit denen deutlich einfacher rumhantieren kann in den meisten Fällen. Aber um das alles an eine Funktion zu übergeben muss man einen String dann eben doch wieder in const char* umwandeln.

    Probier es doch mal aus, statt es vorher abzulehnen.



  • Ich lehne das nicht ab, so war das nicht gemeint.

    Der Nutzen ist mir vollkommen klar und auch nachvollziehbar^^

    Allerdings ist mir das ein wenig zu "leicht". Da ich gerade erst mit C++ angefangen habe möchte ich am liebsten "ganz unten" anfangen, falls ihr versteht wie ich das meine.
    Wenn ich mal auf dem Stand bin das ich eh weiß wie es im Hintergrund alles funktioniert greife ich natürlich auf fertige Klasse wie zB String zurück. Aber vorher möchte ich um des Lernens willen gern so weit wie möglich bei den Basics bleiben.



  • phost schrieb:

    Ich lehne das nicht ab, so war das nicht gemeint.

    Der Nutzen ist mir vollkommen klar und auch nachvollziehbar^^

    Allerdings ist mir das ein wenig zu "leicht". Da ich gerade erst mit C++ angefangen habe möchte ich am liebsten "ganz unten" anfangen, falls ihr versteht wie ich das meine.
    Wenn ich mal auf dem Stand bin das ich eh weiß wie es im Hintergrund alles funktioniert greife ich natürlich auf fertige Klasse wie zB String zurück. Aber vorher möchte ich um des Lernens willen gern so weit wie möglich bei den Basics bleiben.

    machs lieber umgekehrt. Dieses "erstmal von grundauf lernen" entwickelt sich leider oftmals zu einer schwer heilbaren krankheit, weil du ab irgendeinem Punkt alles mit dn Grundwerkzugen "irgendwie" hin kriegst und sich das "Neulernen" auf dem rsten Blick nicht lohnt. Aber eigentlich ist es genau umgekehrt, wenn man das high-level Zeugs drauf hat, braucht man den low-level kram gar nicht mehr.



  • Hm ja das macht sogesehen Sinn 😃

    Allerdings ist mir immer etwas unwohl dabei wenn ich etwas abstrahiertes benutze und ich eigentlich keinen Plan davon habe was intern tatsächlich passiert.



  • phost schrieb:

    Allerdings ist mir immer etwas unwohl dabei wenn ich etwas abstrahiertes benutze und ich eigentlich keinen Plan davon habe was intern tatsächlich passiert.

    Ja, aber die Theorie dahinter kannst du dir ja anlesen.
    Um sie zu verstehen, musst du es nicht zwingend selber implementieren.
    Ich benutze auch std::vector ohne je einen implementiert zu haben, habe aber doch ein gutes Verständnis, was intern abläuft.


Anmelden zum Antworten