memcpy-Problem mit InternetReadFile



  • Schönen guten Tag!
    Ich probiere schon seit längerem an meinem Programm rum. Und zwar möchte meine dynamisch-reservierte Variable "save" nicht richtig gefüllt werden. Ich kompiliere das Programm mit: gcc Internet.c -o Internet.exe -lwininet

    Hier das Programm:

    #include <windows.h>
    #include <wininet.h>
    #include <stdio.h>
    #include <string.h>
    
    int httpGet(char *url, char *save)
    {
    
    	HINTERNET hOpen, hUrl;
        const char UAGENT[] = "Rechnerkiste";
        if(hOpen = InternetOpen(UAGENT, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0))
        {
            if(hUrl = InternetOpenUrl(hOpen, url, NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, 0))
            {
                const unsigned int BUFSIZE = 1024;
                char buf[BUFSIZE];
                DWORD read;
                int save_size = 0;
    
                while(InternetReadFile(hUrl, buf, sizeof(buf) - 1, &read) && read)
                {
                   save_size += read;
                   save = malloc(save_size * sizeof(char));
                   memcpy(save + save_size - read, buf, read);
                   printf("%d\n", strlen(save));
                }
                InternetCloseHandle(hUrl);
            }
            InternetCloseHandle(hOpen);
        }
        return 0;
    }
    
    int main()
    {	
    	char *save;
    	httpGet("http://www.c-plusplus.net/cms/index.php", save);
    	free(save);
    	return 0;
    }
    

    Ich möchte den durch InternetReadFile() heruntergeladenen Inhalt nicht speichern, sondern in save ablegen.
    Könnt ihr mir helfen, das Problem von memcpy() (Zeile 24) zu finden?
    Danke!
    Euer Eisjürgen



  • save = malloc(save_size * sizeof(char)); 
    memcpy(save + save_size - read, buf, read);
    

    ich denke mal das Problem ist, dass du jedes mal wieder malloc aufrufst, und dadurch save nen komplett neuen Speicherbereich zuweist.



  • Am besten lernst du zuerst die Grundlagen.
    Dynamische Speicherverwaltung etc..



  • lowbyte_ schrieb:

    Am besten lernst du zuerst die Grundlagen.
    Dynamische Speicherverwaltung etc..

    Wenn du ihm nicht helfen willst, dann brauchst du hier auch nicht reinschrieben. Zumal das mit der dynamischen Speicherverwaltung kein einfaches Thema ist.



  • Schau dir mal realloc an, das vergrößert den Speicherbereich und kopiert die Daten auch an die neue Stelle.

    main bekommt von der Änderung an save nichts mit. Daher musst du die Adresse von save an httpGet übergeben.

    int httpGet(char *url, char **save); 
    
    int main()
    {   
        char *save;
        httpGet("http://www.c-plusplus.net/cms/index.php", &save);
        puts(save);
        free(save);
        return 0;
    }
    

    httpGet musst du aber selber anpassen. 🙂



  • DirkB schrieb:

    Schau dir mal realloc an, das vergrößert den Speicherbereich und kopiert die Daten auch an die neue Stelle.

    main bekommt von der Änderung an save nichts mit. Daher musst du die Adresse von save an httpGet übergeben.

    int httpGet(char *url, char **save); 
    
    int main()
    {   
        char *save;
        httpGet("http://www.c-plusplus.net/cms/index.php", &save);
        puts(save);
        free(save);
        return 0;
    }
    

    httpGet musst du aber selber anpassen. 🙂

    wie müsste httpGet dann aussehen?



  • int httpGet() {
        /*...*/
        save_size += read;
        save = realloc(save, save_size * sizeof(char));
    
        if (save != NULL) { /* thou shall not follow the NULL pointer, chaos and madness await you at the end ;P */
            /* memcpy here */
        }
        /*...*/
    }
    
    int main() {   
        char *save = NULL; /* wichtig weil realloc sonst Mist baut */
        httpGet("http://www.c-plusplus.net/cms/index.php", save);
        free(save);
        return 0;
    }
    


  • Das klappt so nicht...
    Save muss per Referenz übergeben werden, daher hat DirkB auch die Möglichkeit mit dem Zeiger auf Zeiger gezeigt 🤡
    Auch sollte es statt

    save = realloc(save, save_size * sizeof(char));
    

    besser

    char* p = realloc(save, save_size);
    

    heißen. Nun kann p gegen Null getestet werden und anschließend p an save zugewiesen werden. Denn wenn p wirklich 0 ist, enstände somit kein Speicherleck und der bisherige Inhalt von save bliebe erhalten.

    Ach ja, bei der richtigen Verwendung von realloc ist kein memcpy nötig.

    Der Aufruf von httpGet und die Freigabe mittels free ist mMn eher unschön.

    int httpGet(const char *url, char **save); // Laden, Speicher allokieren
    void httpFree(char **save); // Freigabe
    

Anmelden zum Antworten