Search code examples
cmemory-managementmemory-leaks

Where is memory definitely lost here?


I have made a function in C that handles write callback from cURL.

static size_t writecallback(char* contents, size_t size, size_t nmemb, char** stream) {
    size_t csize=size*nmemb;
    size_t psize = strlen(*stream);
    size_t tsize = csize+ psize;
    *stream = (char*)realloc(*stream, tsize+1);
    memcpy(*stream + psize, contents,csize);
    (*stream)[tsize] = '\0';
    return csize;
}

I don't know how to write in C correctly, I got lost memory here. I used valgrind to check for memory leak, report message looked something like this:

906 bytes in 1 blocks are definitely lost in loss record 859 of 931
at 0x4848B80: realloc (vg_replace_malloc.c:1690)

I tried using chatgpt but it didn't help me much.

With that function I do this ( reproducible example ):

char* request(){
    CURL* curl=curl_easy_init();
    struct curl_slist* header=NULL;

    char* output=malloc(1);
    output[0]='\0';
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &output);
    CURLcode res = curl_easy_perform(curl);
    if(res!=CURLE_OK){
        printf("Failed performing actions,\n%s\n",       
        curl_easy_strerror(res));
    }
    return output;
}
const char* out=request();
//forward logic here

Sorry I don't really know how to write reproducible examples.

What to do here? What did I do wrong? Can you please tell me what did I do wrong so I will know for next time? Thanks for reading.


Solution

  • You need to deallocate memory that you allocate after you're done with it. You're missing free( out );.


    As mentioned in the comments, there are a couple of unrelated issues.

    • char** might not be compatible with void *. They could even have different sizes! That is why

      static size_t writecallback( ..., char **stream ) {
         ...
      }
      

      should be

      static size_t writecallback( ..., void *userdata ) {
         char **stream = userdata;
         ...
      }
      

      The assignment will generate the proper code for converting the void* back into a char**.

    • realloc could return NULL. On a machine with virtual memory, this means your program will crash if you run out of memory. That's probably fine, but it would be best to provide a relevant error message. But if this program is to run on a machine without virtual memory, this is something you need to handle.