Wie Puffer mit malloc() füllen?



  • Hallo!

    Ich bin schon seit längerem am Tüfteln, wie ich den Puffer hier fülle. Das Problem dabei ist, dass irgendwie immer nur die Größe von buf reserviert wird. Aber die Größe von buf soll ja an save drangehängt werden, also nach jedem Durchlauf addiert werden.

    #define BUFSIZE 1024
    [...]
    char buf[BUFSIZE];
    int n;
    char *save;
    int i = 0;
    
    while ((n = recv(sock, buf, BUFSIZE -1, 0)) > 0) {
        i++;
        buf[n] = 0;
        save = malloc(sizeof(buf) * i);
        strcat(save, buf);
    }
    
    printf("%s\n", save); //Gibt nur die letzten 1024 Zeichen (BUFSIZE) aus
    [...]
    

    Könnt ihr mir eventuell auch helfen, den Code zu optimieren? 🙂

    MfG
    Danke



  • Du kannst mit malloc nix an einen bestimmten Bereich 'anhängen'. malloc besorgt Dir immer neuen Speicher irgendwo auf dem Heap.
    Du müsstest zu diesem Zweck also neuen Speicher in der Größe (alter Speicher + benötigter neuer Speicher) via malloc anfordern, den Inhalt des alten Speicherbereichs in den neuen umkopieren, den Rest (also den zusätzlich angeforderten Speicher) mit den gewünschten Daten füllen, und den alten Speicherbereich, der nun nicht mehr benötigt wird, mittels free freigeben.



  • Ungefähr so (nicht getestet):

    #define BUFSIZE 1024
    [...]
    char buf[BUFSIZE];
    
    int n;
    char *save = 0;
    char *tmp;
    
    int gesamt = 0;   //insgesamt mit recv empfangen
    
    while ((n = recv(sock, buf, BUFSIZE -1, 0)) > 0) {
        gesamt = gesamt + n;           
        tmp = malloc(gesamt + 1);          //Speicher für Gesamtmenge + '\0' anfordern
        memcpy(tmp, save, gesamt - n);     //bisher gelesenes umkopieren
        free(save);                        //alten Speicher freigeben
        memcpy(tmp + gesamt - n, buf, n);  //gerade Gelesenes anhängen
        save = tmp;                        //save auf den neuen, größeren Speicherbereich setzen
    }
    save[gesamt] = 0;
    printf("%s\n", save);
    


  • Hallo,

    das Zauberwort heißt realloc. Außerdem solltest Du statt strcat strcpy benutzen.

    #define BUFSIZE 1024
    [...]
    char buf[BUFSIZE];
    int n;
    char *save=NULL;
    int i = 0;
    int j=0;
    
    while ((n = recv(sock, buf, BUFSIZE -1, 0)) > 0) {
        i++;
        buf[n] = 0;
        save = reallloc(save, sizeof(buf) * i);
        strcpy(save+j, buf);
        j+=n;
    }
    
    printf("%s\n", save); //Gibt nur die letzten 1024 Zeichen (BUFSIZE) aus
    [...]
    

    Beachte, wenn Dein Protokoll Binärdaten überträgt, solltest Du statt strcpy memcpy benutzen, da auch 0 bytes innerhalb des Streams vorkommen könnten.

    mfg Martin



  • mgaeckler schrieb:

    Beachte, wenn Dein Protokoll Binärdaten überträgt, solltest Du statt strcpy memcpy benutzen, da auch 0 bytes innerhalb des Streams vorkommen könnten.

    Aha, also unterschiedlichen Code je nachdem, was für Daten kommen könnten?
    Es geht auch alles ohne jegliche str-Funktion, dann braucht man sich auch nicht auf irgendwelche Aussagen zum Datenstrominhalt und ob nun '\0' vorkommen kann oder nicht verlassen.

    #define BUFSIZE 1024
    [...]
    unsigned char  buf[BUFSIZE];
    unsigned char *save = 0;
    int n, gesamt = 0;
    
    while ((n = recv(sock, buf, BUFSIZE, 0)) > 0) {
        gesamt += n;
        save = realloc(save, gesamt);
        /* hier evtl. noch Fehlerbehandlung: if( !save ) ... */
        memcpy( save+gesamt-n, buf, n );
    }
    
    fwrite( save, gesamt, 1, stdout ); fflush(stdout);
    [...]
    


  • Wutz schrieb:

    while ((n = recv(sock, buf, BUFSIZE, 0)) > 0) {
        gesamt += n;
        save = realloc(save, gesamt);
        /* hier evtl. noch Fehlerbehandlung: if( !save ) ... */
        memcpy( save+gesamt-n, buf, n );
    }
    

    Und jetzt kommt eine 3GB große MPG-Datei angeflogen, die den maximalen virtuellen Speicher einer Anwendung sprengt. Warum also nicht gleich z.B. in eine Datei schreiben?
    Okay, der TE wollte wissen, wie der Speicherbereif vergrößert und umkopiert werden kann, es sollte aber noch einmal überdacht werden, ob dies in diesem Zusammenhang Sinn macht.



  • wieso muß der buffer(buf) überhaupt iwo hin kopiert werden? das ist doch total sinnbefreit.(es sollte doch schon im recv() vom netzwerk stack in den userspace kopiert werden?)



  • Vielen Dank für eure zahlreichen helfenden Antworten!

    ...ich möchte den Strom nicht als Datei speichern, da ich ihn direkt verarbeiten und danach wieder verwerfen möchte. Es wäre eine Zeit- und Rechenverschwendung, wenn ich den Strom als Datei zwischenspeichern würde.



  • _-- schrieb:

    wieso muß der buffer(buf) überhaupt iwo hin kopiert werden? das ist doch total sinnbefreit.(es sollte doch schon im recv() vom netzwerk stack in den userspace kopiert werden?)

    Wenn der Empfänger vorher nicht weiß wie viele Daten ankommen, kann er nicht in Voraus einen genügend großen Block anfordern, Wenn die Daten aber an einem Stück vorliegen müssen, kommt er nicht darum, sie in Häppchen zu lesen und dann zusammen zu fügen.

    mfg Martin



  • Wutz schrieb:

    Aha, also unterschiedlichen Code je nachdem, was für Daten kommen könnten?

    Wo er recht hat, hat er recht. Das war natürlich Unfug von mir. Naja so früh am Morgen möge man mir das verzeihen.

    mfg Martin


Anmelden zum Antworten