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.

Libcurl curl_slist_append() leads to memory leak.

From: Iku_ex Diaz via curl-library <curl-library_at_lists.haxx.se>
Date: Fri, 22 Apr 2022 15:10:03 +0200

*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
Received on 2022-04-22