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.
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: Kerry Loux via curl-library <curl-library_at_lists.haxx.se>
Date: Fri, 22 Apr 2022 09:28:21 -0400
It looks like you're missing a call to curl_slist_free_all().
See: https://curl.se/libcurl/c/curl_slist_append.html
-Kerry
On Fri, Apr 22, 2022 at 9:25 AM Iku_ex Diaz via curl-library
<curl-library_at_lists.haxx.se> 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
Date: Fri, 22 Apr 2022 09:28:21 -0400
It looks like you're missing a call to curl_slist_free_all().
See: https://curl.se/libcurl/c/curl_slist_append.html
-Kerry
On Fri, Apr 22, 2022 at 9:25 AM Iku_ex Diaz via curl-library
<curl-library_at_lists.haxx.se> 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.htmlReceived on 2022-04-22