Malloc-Fehler C - Log-Filter-Funktion



  • Hallo,
    ich möchte eine Filterfunktion in C schreiben, die anhand von Keywörtern Log-Dateien durchsucht (ca. 500MB Größe).
    Als Erstes habe ich mir eine Funktion geschrieben, die eine Map der Datei erstellt und ein Globales int *array (die Map) mit den Zeilenlängen füllt:

    //Globale Variable - der Dateiname, der geöffnet werden soll
    char *filename_orig="test.log";
    
    //Mapping-Funktion
    int *filemap(){
        FILE *file=fopen(filename_orig, "r");
        int lines_counter=0;
        int columns=0;
        linesmap=malloc(sizeof(int)*2);
        int c=0;
        while((c=getc(file))!=EOF){
            if(c=='\n'){
                linesmap=realloc(linesmap, sizeof(int)*lines_counter+1);
                linesmap[lines_counter]=columns+1;
                columns=0;
                lines_counter++;
            }else{
                columns++;
            }
        }
        fclose(file);
        rows=lines_counter;
        return 0;
    }
    

    Die Funktion arbeitet auch schon ohne weitere Probleme, doch die folgende Funktion macht Probleme beim "richtigen" Laden der Datei:

    int f_loader(){
    
    char *puffer=NULL;
    
    //Zeilencounter
    int counter=0;
    //Datei im Lesemodus öffnen
    FILE *file=fopen(filename_orig, "r");
    
    //Rows ist die gesamt Zeilenanzahl, die in der Funktion filemap ermittelt wurde
    while(counter!=rows){
    puffer=malloc(sizeof(char)*linesmap[counter]+1);//In dieser Zeile Bricht das Programm mit einem Malloc-Error ab
    fgets(puffer, linesmap[counter]+10, file);
    counter++;
    }
    return 0;
    }
    

    Weiß jemand vielleicht, warum das Programm einfach so an dieser Stelle abbricht und den String nicht "Malloc-en" kann?
    Bei kleineren Log-Dateien treten auch keine Fehler auf, nur bei Größeren, die über die ca. 500 MB gehen, tritt der Malloc-Fehler auf... Ich habe mir auch einige Debug-Infos anzeigen lassen, z.B. die momentane Zeilenlänge: Das stimmt auch vollkommen mit der zu lesenden Dateilänge überein.

    Der Malloc-Error, den ich hier erwähnt habe ist außerdem:

    malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
    Abgebrochen
    

    Ich würde mich Freuen, wenn jemand hier so etwas vielleicht schon einmal hatte und dann vielleicht auch eine Lösung des Problems kennt. 🙂

    Viele Grüße



  • Besser:

    linesmap=realloc(linesmap,++lines_counter*sizeof*linesmap);
                linesmap[lines_counter-1]=columns+1;
    

    Außerdem hast du Probleme, falls deine letzte Zeile der Datei nicht mit '\n' endet.
    Auch kann ein Test des Rückgabewertes bei malloc nicht schaden.
    Globale Variablen sind Schrott.



  • fgets(puffer, linesmap[counter]+10, file);
    

    Soll da wirklich die 10 stehen?
    Der Fehler (Assertion) deutet auf einen Speicherüberschreiber hin.

    Aber generell erscheint mir dein Vorgehen eigenartig um eine Datei zu lesen.
    Du kannst doch gleich Zeile für Zeile lesen und die Schlüsselwörter bestimmen (anstatt die gesamte Datei in den Speicher zu laden - außer du willst einen Editor schreiben ;-).


  • Mod

    Th69 schrieb:

    Aber generell erscheint mir dein Vorgehen eigenartig um eine Datei zu lesen.
    Du kannst doch gleich Zeile für Zeile lesen und die Schlüsselwörter bestimmen (anstatt die gesamte Datei in den Speicher zu laden - außer du willst einen Editor schreiben ;-).

    QFT. Außerdem programmiert der Threadersteller gerade das verbreitete (und als Open Source erhältliche) Werkzeug "grep" nach, falls ihm das nicht bewusst ist. Abgesehen davon, dass grep auf sämtlichen Unix-artigen Systemen verfügbar ist, gibt es auch auf MS-DOS-artigen Plattformen (Windows :p ) ein fertiges Werkzeug mit der gleichen Funktion: Findstr.



  • Th69 schrieb:

    fgets(puffer, linesmap[counter]+10, file);
    

    Soll da wirklich die 10 stehen?
    Der Fehler (Assertion) deutet auf einen Speicherüberschreiber hin.

    Aber generell erscheint mir dein Vorgehen eigenartig um eine Datei zu lesen.
    Du kannst doch gleich Zeile für Zeile lesen und die Schlüsselwörter bestimmen (anstatt die gesamte Datei in den Speicher zu laden - außer du willst einen Editor schreiben ;-).

    Nein, Sry, das war ein Fehler, da hab ich eine 0 zuviel hingeschrieben, die war nur zum testen, ob der Puffer, vllt zu klein war und es an einer falschen Zeilenzahl irgendwie lag...

    Das Problem ist, wie soll ich eine Datei Zeile für Zeile Laden, wenn ich nicht weiß, wie lang die Zeile ist? Die Zeilenanzahl ist jedes mal unterschiedlich lang 😞 Ansonsten hätte ich auch einen Fixen Puffer mit char puffer[] anlegen können.

    Das Zeile Für Zeile Hat den Hintergrund, dass ich aus der Log-Datei eine andere Datei generiere, in der dann Details drin stehen. Es sollen ja keine Wörter abgeschnitten werden. Die Datei wird dann wiederum in eine GUI in eine Tabelle eingelesen - Format:
    Timestamp | Absender | Empfänger | IP

    PS: es handelt sich bei den Log-Dateien immer um Prozesse, die beim Verarbeiten einer E-Mail auftreten. Deshalb auch das Format



  • Wutz schrieb:

    Besser:

    linesmap=realloc(linesmap,++lines_counter*sizeof*linesmap);
                linesmap[lines_counter-1]=columns+1;
    

    Außerdem hast du Probleme, falls deine letzte Zeile der Datei nicht mit '\n' endet.
    Auch kann ein Test des Rückgabewertes bei malloc nicht schaden.
    Globale Variablen sind Schrott.

    Ich verstehe nicht ganz, warum du sizeof*linesmap verwendest, muss man bei sizeof nicht in () den Typ eintragen? und Linesmap hat dann einen Int-Wert, auch, wenn es ein int * ist? das versteh ich irgendwie noch nicht ganz...

    Doch danke, für den Tipp. Das Merkwürdige ist, es funktioniert bei "kleineren" Dateien einwandfrei, ohne Probleme, bei ca. 500MB dauert die Auswertung ca. 25 sek. (hab nachgemessen)
    Mit Test des Rückgabewertes meinst du sicherlich eine Prüfung, ob columns!=NULL ist oder?


Log in to reply