Search code examples
c++linked-liststack-overflowshared-ptr

Using shared_ptr for linked_list gives stackoverflow within destructor


I'm trying to implement a linked list using shared_ptr rather than raw pointers. The code :

#include <memory>
class NodeTest
{
private:
    int v;
    std::shared_ptr<NodeTest> next;
public:
    NodeTest() { v = 0; };
    NodeTest(unsigned int i) { v = i; }
    ~NodeTest() {};
    void setNext(std::shared_ptr<NodeTest> & toSet) { next = toSet; }
};

std::shared_ptr<NodeTest> init()
{
    std::shared_ptr<NodeTest> elt = std::shared_ptr<NodeTest>(new NodeTest());
    std::shared_ptr<NodeTest> first = elt;
    for (unsigned int i = 1; i < 5000; i++)
    {
        std::shared_ptr<NodeTest> next(new NodeTest(i));
        elt->setNext(next);
        elt = next;
    }
    return first;
}

void test_destroy()
{
    std::shared_ptr<NodeTest> aList = init();
}


int main(int argc, char * argv[])
{
    test_destroy();
}

This is generating a stackoverflow when leaving test_destroy() scope because of the call to aList destructor (RAII). To destroy aList, it calls the destructor of next and so on, which obviously ends up with a stackoverflow for a sufficiently large list.

I can't find any efficient way to fix this. The ideal case would be to delete the current NodeTest before moving to next deletion, right? How would you do such a thing?

Thanks in advance

Solution : You need to break the links between all nodes AND save a pointer to each node so that the destructor is not immediatly called upon breaking links. Example below using a vector.

~NodeTest() 
{
    std::vector<std::shared_ptr<NodeTest>> buffer;
    std::shared_ptr<NodeTest> cursor = next;

    while (cursor.use_count()!=0)
    {
        std::shared_ptr<NodeTest> temp = cursor->getNext();
        cursor->setNext(std::shared_ptr<NodeTest>());
        buffer.push_back(cursor);
        cursor = temp;
    }

    next = std::shared_ptr<NodeTest>();
};

Solution

  • In this case you should manage nodes deleting manually because destructor calls destructor calls destructor .....

    Take a look on the talk CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”