dimanche 6 février 2022

Memory leak with std::string depends on string size

I am getting a memory leaking in C++ depending on the string size. On the code bellow if the string size is less than 15 valgrind doesn't shows leak, however if string size is greater than 15 I am getting memory leaks:

#include <string>
#include <memory>
#include <iostream>

class AuthBase {
public:
    virtual void foo() = 0;
};

class APIAuthetication : public AuthBase {
public:
    APIAuthetication(const std::string api_key, const std::string api_secret) : m_api_key(api_key),
                m_api_secret(api_secret) {}
    
    virtual ~APIAuthetication() {}

    void foo() {}
private:
    const std::string m_api_key;
    const std::string m_api_secret;
};

class ClientBase {
public:
    virtual void bar() = 0;
};

class Client: public ClientBase {
public:
    Client(AuthBase* auth) : m_auth(auth) {}
    ~Client() {}

    void bar() {}
private:
    std::unique_ptr<AuthBase> m_auth;
};

class ClientAPI : public Client {
public:
    ClientAPI(const std::string api_key, const std::string api_secret) : 
                Client((new APIAuthetication(api_key, api_secret))) {}
    virtual ~ClientAPI() {}
};

int main(void) {
    /* This runs fine. String size == 15 */
    ClientAPI cli("123456789101112", "123456789101112");
    /* Memory leak. String size > 15 */
    ClientAPI cli_leak("1234567891011121", "1234567891011121");
    return 0;
}
==17060== HEAP SUMMARY:
==17060==     in use at exit: 34 bytes in 2 blocks
==17060==   total heap usage: 9 allocs, 7 frees, 72,950 bytes allocated
==17060== 
==17060== Searching for pointers to 2 not-freed blocks
==17060== Checked 111,624 bytes
==17060== 
==17060== 17 bytes in 1 blocks are definitely lost in loss record 1 of 2
==17060==    at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17060==    by 0x4F6513C: void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==17060==    by 0x1091B3: APIAuthetication::APIAuthetication(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (in /home/rogerio/code-studies/curl-examples/weird)
==17060==    by 0x10937C: ClientAPI::ClientAPI(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (in /home/rogerio/code-studies/curl-examples/weird)
==17060==    by 0x108FD3: main (in /home/rogerio/code-studies/curl-examples/weird)
==17060== 
==17060== 17 bytes in 1 blocks are definitely lost in loss record 2 of 2
==17060==    at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17060==    by 0x4F6513C: void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==17060==    by 0x1091CA: APIAuthetication::APIAuthetication(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (in /home/rogerio/code-studies/curl-examples/weird)
==17060==    by 0x10937C: ClientAPI::ClientAPI(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (in /home/rogerio/code-studies/curl-examples/weird)
==17060==    by 0x108FD3: main (in /home/rogerio/code-studies/curl-examples/weird)
==17060== 
==17060== LEAK SUMMARY:
==17060==    definitely lost: 34 bytes in 2 blocks
==17060==    indirectly lost: 0 bytes in 0 blocks
==17060==      possibly lost: 0 bytes in 0 blocks
==17060==    still reachable: 0 bytes in 0 blocks
==17060==         suppressed: 0 bytes in 0 blocks
==17060== 
==17060== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==17060== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

No leaks if string size is < 15:

==17211== 
==17211== HEAP SUMMARY:
==17211==     in use at exit: 0 bytes in 0 blocks
==17211==   total heap usage: 2 allocs, 2 frees, 72,776 bytes allocated
==17211== 
==17211== All heap blocks were freed -- no leaks are possible
==17211== 
==17211== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==17211== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I know that if a string is less than 16 bytes it doesn't allocate memory and uses a char buffer (optimization), but makes no sense to me this memory leak. Does anyone have an idea what is wrong with my code?

Aucun commentaire:

Enregistrer un commentaire