Search code examples
cstringmalloclibcurl

C return libcurl response from example as parameter


I'm following the code from this libcurl example and everything seems to work perfectly as a standalone, so i wanted to make it a function in its own file to reuse in other code.

I added two parameters, one char *addr for the web address and another char *response to retrieve the response from curl, so the template became

extern int curlGet(char *addr, char *response);

and i return the resulting response with a

memcpy(response,chunk.memory,chunk.size+1);

and then i call it on my main file with the following code

int main(void){
    char *tmp=malloc(1);
    curlGet("www.google.com",tmp);
    printf("%s\n",tmp);
    //free(tmp);
    return 0;
};

The addr parameter works without a problem, but the tmp one constantly throws a segmentation fault (core dumped), and if i uncomment the free(tmp) i get a

free(): invalid next size (fast)
Aborted (core dumped)

my instincts tell me its something with memory allocation, but i'm too new to c to know why.

**Edit from comments This is the modifications i made to the example to try to return the answer:

if(res!=CURLE_OK){
    fprintf(stderr, "curl_easy_perform() failed: %s\n",
        curl_easy_strerror(res));
    return -1;
}
curl_easy_cleanup(curl_handle);
memcpy(response,chunk.memory,chunk.size+1);
free(chunk.string);
return 0;

Solution

  • From the fragments you provided I think, this is what you are looking for:

    Modification to the linked example:

    void curlGet(const char *URL, char **Buffer)
    {
      CURL *curl_handle;
      CURLcode res;
     
      struct MemoryStruct chunk;
    ...
      /* get it! */
      res = curl_easy_perform(curl_handle);
     
      /* check for errors */
      if(res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
      }
      else {
        /*
         * Now, our chunk.memory points to a memory block that is chunk.size
         * bytes big and contains the remote file.
         *
         * Do something nice with it!
         */
    
        *Buffer = chunk.memory;     // <<< Assign the buffer to the address you provided.
     
        printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
      }
     
      /* cleanup curl stuff */
      curl_easy_cleanup(curl_handle);
     
    //   free(chunk.memory);   // <<< DO NOT FREE THIS MEMORY. WE STILL USE IT!
     
      /* we are done with libcurl, so clean it up */
      curl_global_cleanup();
    }
    
    int main(void)
    {
        char *tmp = NULL;
        curlGet("www.google.com", &tmp);  // Pass the address of your pointer.
    
        printf("%s\n",tmp);
    
        free(tmp);  // Now you must free it here instead of in curlGet.
        return 0;
    };
    

    You do not reserve any memory inside your curlGet function. You simply use memcpy to dump all the content to your reserved buffer that can only take 1 byte. This results in undefined behaviour which causes a segfault in your case.

    You must provide more memory. And this is already done in the callback of the linked example. You just need to provide it to the caller.

    In C all parameters are passed by value. That means if you pass tmp to curlGet, then the function only gets a copy. You cannot change it inside your function as the change would not be visible at the caller.

    Therefore you must pass &tmp instead.