i was writing a simple code for testing purposes. if i declare the node1
first, there's no problem but when i declare the node2
first, the code give me free(): double free detected in tcache2
.
could someone please explain the reason for this
double free
error?class node1; class node2; class node1{ public: node1(void) = default; // member data int *n; std::set<node2*> tonode2; }; class node2{ public: node2(void) = default; ~node2(void){ for(auto val:tonode1) val->tonode2.erase(this); // free(): double free detected here.. } // member data int *n; std::set<node1*> tonode1; }; int main(void){ node2 n2; node1 n1; n1.tonode2.insert(&n2); n2.tonode1.insert(&n1); return 0; }
the code compiled with g (GCC) 11.2.0 run on ubuntu 20.04.
CodePudding user response:
n1
is destroyed first. When n2
is destroyed, its destructor will indirect through the pointer that used to point to n1
, but is now invalid. The behaviour of the program is undefined.
CodePudding user response:
You better use smart pointers such as std::shared_ptr
instead of raw pointers when ownership is important. std::weak_ptr
should be preferred if there are reference cycles as in your question.
And you should create them with std::make_shared
in the main, so that objects will be owned by smart pointer. Because smart pointers assume they are the only owner of the enclosed object. Otherwise it will be destructed two times, once by the owner scope and once by the smart pointer, leading to a double free corruption.