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?
std::stringaround to constructors, make it a const reference. Otherwise you're just creating copies for no reason.std::stringimplementations use so-called small string optimization - there's a small buffer insidestd::stringobject itself, and if the string is short enough, it's stored in this buffer, avoiding heap allocation. Longer strings are allocated on the heap. Naturally, if heap allocation is avoided this way, there's nothing to leak.