The code below ends up with free(): double free detected in tcache 2
. I want to know the inner process the error happens through.
#include <string>
class test
{
private:
std::string member;
public:
test(const std::string & arg) { member = arg; };
};
int main()
{
test T = test("test test test test");
T.~test();
return 0;
}
The error depends on the length of the given string; if you change "test test test test"
to "test"
, the program runs fine, at least with g++
on my computer.
std::string
has an internal buffer for short strings to avoid memory allocations. If the string is short, then there is no memory to free and it works. If the string is long it tries to free the buffer each time you call the destructor.
Here is more information on the Short String Optimization: Meaning of acronym SSO in the context of std::string
In your code test T
is a local variable and local variables are deleted when they go out of scope.
If you call T.~test()
explicitly then it deletes the variable before it goes out of scope. But when the variable really goes out of scope, the destructor is called again.
Consider the example (taken from your code):
#include <string>
#include <iostream>
class test
{
private:
std::string member;
public:
test(const std::string & arg) { member = arg; };
~test()
{
std::cout << " calling destructor "<<std::endl;
}
};
int main()
{
test T = test("test test test test");
//take the call away and you will still have the destructor call
//T.~test();
return 0;
}
If now, you call the destructor explicitly, then you get the destructor called twice (once explicitly and once when the variable goes out of scope)
#include <string>
#include <iostream>
class test
{
private:
std::string member;
public:
test(const std::string & arg) { member = arg; };
~test()
{
std::cout << " calling destructor "<<std::endl;
}
};
int main()
{
test T = test("test test test test");
//causing a double call to the destructor
T.~test();
return 0;
}
The execution would be
calling destructor
calling destructor
free(): double free detected in tcache 2
Abandon
If instead, you have allocated a pointer on test
with new
, you then need to explicitly call the destructor otherwise, you will have memory leaks.
When excuting the code below, you see that the destructor does not get called even if your pointer goes out of scope.
int main()
{
test* T = new test("test test test test");
// in this case you will have no more destructor automatically
//T.~test();
return 0;
}
You need to deallocate the allocated memory explicitly by calling the destructor but not by using T.~test()
because now T
is not of type test
but test*
. You only need to call delete T
like this:
int main()
{
test* T = new test("test test test test");
//You need to deallocate the allocated memory explicitly
//T.~test();
delete T;
return 0;
}
And the destructor is called on the allocated memory
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With