Firstly, I really checked if there is a question already been asked but I could not find any. Error message should not deceive you my situation is a bit different I guess or I am just missing something.
While I was dealing with a toy C++ code I encountered with a weird error. Program output says there is double free situation but I cannot see the place where this error occurs. Code may be seen a bit long, I apology for that.
I am working on a Linux Distribution
right now and I am using g++ 9.1.0
. I checked my code and looked for erroneous part.
Even though I fixed some part of code, my problem did not get solved except when I comment either Foo{1, "Hello World"};
or vec.push_back(std::move(Foo{}));
and I don't get it why.
class Foo
{
public:
Foo()
: val{nullptr}, str{nullptr}
{
std::cout << "You are in empty constructor\n";
}
Foo(int the_val, const char *the_str)
: val{new int}, str{new char[std::strlen(the_str + 1)]}
{
*val = the_val;
std::cout << *val << '\n';
std::strcpy(str, the_str);
std::cout << str << '\n';
}
~Foo()
{
if (val) {
delete val;
} else {
std::cout << "val is empty\n";
}
if (str) {
delete[] str;
} else {
std::cout << "str is empty\n";
}
}
Foo(const Foo&) = delete;
Foo& operator= (const Foo&) = delete;
Foo(Foo&& rhs)
{
std::cout << "Move constructor is triggered\n";
if (val) {
delete val;
}
val = rhs.val;
rhs.val = nullptr;
if (str) {
delete[] str;
}
str = rhs.str;
rhs.str = nullptr;
}
Foo& operator= (Foo& rhs)
{
std::cout << "Move assignment is triggered\n";
// Self-assignment detection
if (&rhs == this) {
return *this;
}
if (val) {
delete val;
}
val = rhs.val;
rhs.val = nullptr;
if (str) {
delete[] str;
}
str = rhs.str;
rhs.str = nullptr;
return *this;
}
private:
int *val;
char *str;
};
int main()
{
Foo{1, "Hello World"};
std::vector<Foo> vec;
vec.push_back(std::move(Foo{}));
return 0;
}
If I do not comment any place in function main, output is as follows.
1
Hello World
You are in empty constructor
val is empty
str is empty
You are in empty constructor
Move constructor is triggered
free(): double free detected in tcache 2
Aborted (core dumped)
If I comment "Foo{1, "Hello World"};", output becomes
You are in empty constructor
Move constructor is triggered
val is empty
str is empty
val is empty
str is empty
and finally, when I comment "vec.push_back(std::move(Foo{}));", output becomes
You are in empty constructor
Move constructor is triggered
val is empty
str is empty
val is empty
str is empty