curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Re: Libcurl curl_slist_append() leads to memory leak.

From: Iku_ex Diaz via curl-library <curl-library_at_lists.haxx.se>
Date: Mon, 25 Apr 2022 09:26:24 +0200

Thank you for the help!
Indeed I was missing the call to free the slist (and also re-asign the list
to the append call, which I wasn't doing as well). It solved the problem.

Cheers,
Iker

El vie, 22 abr 2022 a las 15:40, Timothe Litt via curl-library (<
curl-library_at_lists.haxx.se>) escribió:

> Besides not calling curl_slist_free_all() per
> list_append.html <https://curl.se/libcurl/c/curl_slist_append.html>
>
> The list should be freed again (after usage) with curl_slist_free_all
> <https://curl.se/libcurl/c/curl_slist_free_all.html>.
>
>
> (Someone beat me to pointing that out...)
>
> If the code shown is complete, you're not using the headers - you're
> passing a NULL pointer to curl_easy_setopt(). I expect that a trace (or
> verbose output) will show that they aren't being sent. "Seems to work" and
> "does work" are two different things...
>
> Note under "Return value" that the call can fail and that the return value
> is a new list pointer. See the example for proper handling, which requires
> an intermediate variable as well as updating the list pointer to avoid
> leaks.
>
> --
> Timothe Litt
> ACM Distinguished Engineer
> --------------------------
> This communication may not represent the ACM or my employer's views,
> if any, on the matters discussed.
>
>
> On 22-Apr-22 09:10, Iku_ex Diaz via curl-library wrote:
>
> *System*
> x86 with Linux Ubuntu 22.04
>
> *Problem*
> I'm running a program that uses libcurl to perform 3 requests, one GET,
> and two PUT. Using *Valgrind *outputs several memory leaks originated at
> the *curl_slist_append() *calls for the two PUT requests.
>
> *TRACE:*
> ==15078== HEAP SUMMARY:
>
> ==15078== in use at exit: 1,428 bytes in 72 blocks
> ==15078== total heap usage: 8,310 allocs, 8,238 frees, 1,512,884 bytes allocated
> ==15078==
> ==15078== 124 (64 direct, 60 indirect) bytes in 4 blocks are definitely lost in loss record 5 of 12
> ==15078== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==15078== by 0x48A034D: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.6.0)
> ==15078== by 0x48A03BC: curl_slist_append (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.6.0)
> ==15078== by 0x1149CD: DLMController::liberateClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (dlmController.cpp:598)
> ==15078== by 0x113F82: DLMController::stopDLM() (dlmController.cpp:466)
> ==15078== by 0x160259: main (in /home/ikerdiaz/Desktop/dlm/embedded_load_manager/dlm)
> ==15078==
> ==15078== 164 (64 direct, 100 indirect) bytes in 4 blocks are definitely lost in loss record 6 of 12
> ==15078== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==15078== by 0x48A034D: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.6.0)
> ==15078== by 0x48A03BC: curl_slist_append (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.6.0)
> ==15078== by 0x1149A1: DLMController::liberateClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (dlmController.cpp:596)
> ==15078== by 0x113F82: DLMController::stopDLM() (dlmController.cpp:466)
> ==15078== by 0x160259: main (in /home/ikerdiaz/Desktop/dlm/embedded_load_manager/dlm)
> ==15078==
> ==15078== 188 (64 direct, 124 indirect) bytes in 4 blocks are definitely lost in loss record 7 of 12
> ==15078== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==15078== by 0x48A034D: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.6.0)
> ==15078== by 0x48A03BC: curl_slist_append (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.6.0)
> ==15078== by 0x1149B7: DLMController::liberateClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (dlmController.cpp:597)
> ==15078== by 0x113F82: DLMController::stopDLM() (dlmController.cpp:466)
> ==15078== by 0x160259: main (in /home/ikerdiaz/Desktop/dlm/embedded_load_manager/dlm)
>
> The trace is larger. There is always this same leak whenever there is a call to *curl_slist_append(). *The code generating the trace above is the following one (where the lines in orange in the *Valgrind *trace are the calls to curl_slist_append).
>
> *CODE:*
>
> void DLMController::liberateClient(std::string dev_id, std::string ip)
> {
> // Payload
> nlohmann::json free_payload = {
> {"device",
> {
> {"id", dev_id}
> }
> }
> };
>
>
> std::string tmp_str = free_payload.dump(4);
> const char* put_data = tmp_str.c_str();
>
> CURL* curl;
> CURLcode res;
>
> std::string route = ip + "/services/cpi/dlmLimitReset.json";
> const char* ip_dir = route.c_str();
>
> curl = curl_easy_init();
>
> struct curl_slist* headers = NULL;
> curl_slist_append(headers, "Accept: application/json"); // MEMORY LEAK
> curl_slist_append(headers, "Content-Type: application/json"); //MEMORY LEAK
> curl_slist_append(headers, "charset: utf-8"); //MEMORY LEAK
> curl_easy_setopt(curl, CURLOPT_URL, ip_dir);
>
> curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
> curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
> curl_easy_setopt(curl, CURLOPT_POSTFIELDS, put_data);
>
> // CALL
> res = curl_easy_perform(curl);
> // Check for errors.
> if (res != CURLE_OK) {
> std::cout << curl_easy_strerror(res) << std::endl;
> }
>
> // Check return code
> long httpCode(0);
> curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
> curl_easy_cleanup(curl);
>
> if (httpCode != 204 && httpCode != 200) {
> std::cout << "Fail, returned code: " << httpCode << std::endl;
> }
> }
>
> Please note that even if *curl_global_init(0)* and *curl_global_cleanup()* don't appear in the function, they are called in another part of the code before this function is called. This is done once as explained in the documentation. The code does work, meaning that the request is successful and works just fine, although there is this memory leak.
>
> I would highly appreciate it if someone could help me figure this out.
>
> Thank you!
>
> Iker
>
>
> --
> Unsubscribe: https://lists.haxx.se/listinfo/curl-library
> Etiquette: https://curl.haxx.se/mail/etiquette.html
>


-- 
Unsubscribe: https://lists.haxx.se/listinfo/curl-library
Etiquette:   https://curl.haxx.se/mail/etiquette.html
Received on 2022-04-25