Search code examples
c++pointersmemoryfault

Segmentation fault in handwritten singly linked list with many objects


I am dealing with custom written singly linked list at work whose elements are smart pointers to objects. The problem is that after inserting successfully a certain amount of elements in the list (for example 50000), the program crashes with segmentation fault when the list goes out of scope and the elements start getting destructed one by one (by the smart pointer). The 50000 elements are created successfully, but every time the 43256 (for example) object gets destroyed, the program crashes.

Note: When dealing with small number of objects - 5000, 10000, 20000, ... - there is no problem at all.

We use C++98 standart and Boost 1.55.0 C++ libraries.

The program occured on Red Hat, but I also tried it locally on Ubuntu - same deal. What I tried just for the experiment was using std::list, std::vector, boost::container::slist instead of hadwritten singly linked list and the issue is gone. But I really want to understand where the problem comes from.

Here is sample code which reproduces the issue:

#include <iostream>
#include "boost/lexical_cast.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/make_shared.hpp"
#include <vector>

class SmartInt;
typedef boost::shared_ptr<SmartInt> BoostSharedPtrSmartInt;

class SmartInt
{
public:
    int m_data;
    BoostSharedPtrSmartInt m_ptrNext;

    void SetNext(BoostSharedPtrSmartInt ptrNext)
    {
        m_ptrNext = ptrNext;
    }

    BoostSharedPtrSmartInt GetNext() const
    {
        return m_ptrNext;
    }
};

class IntList
{
public:
    BoostSharedPtrSmartInt m_ptrFirst;
    BoostSharedPtrSmartInt m_ptrLast;

    void AddParameter( BoostSharedPtrSmartInt ptrParam ) throw()
    {
        if( m_ptrFirst == NULL )
        {
            std::cout << "ST_TEST First time AddParameter" << std::endl;
            m_ptrFirst = m_ptrLast = ptrParam;
        }
        else
        {
            m_ptrLast->SetNext( ptrParam );
            m_ptrLast = ptrParam;
        }
    }
};

void test3(int numObjects)
{
    IntList list;
    int i = 1;
    for(; i <= numObjects; ++i)
    {
        BoostSharedPtrSmartInt bspsi = boost::make_shared<SmartInt>();
        list.AddParameter( bspsi );
    }
    std::cout << "ST_TEST i = " << i << std::endl;
    std::cout << "ST_TEST Getting out of scope - everything should get destroyed now!" << std::endl;
}

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        std::cout << "Usage: ./test <number of objects created>" << std::endl;
        exit(1);
    }

    test3( boost::lexical_cast< int >( argv[1] ) );
    return 0;
}

To build the project, I use CMakeLists.txt is as follows:

cmake_minimum_required(VERSION 2.6)
project(test)

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

find_package(Boost REQUIRED)

include_directories(${Boost_INCLUDE_DIRS}) 

add_executable(test main.cpp)

target_link_libraries( test
 ${Boost_LIBRARIES} )

Thanks in advance, I am really puzzled why the crash happens and I`ve been dealing with this for 1-2 weeks now...


Solution

  • Your program crashes due to a stack overflow as Botje suspected. You can avoid this by explicitly releasing the list items one-by-one in the list destructor.

    ...
    class SmartInt
    {
    public:
    ...    
        void Reset() {
            m_ptrNext.reset();
        }
    ...
    };
    
    class IntList
    {
    public:
    ...    
        ~IntList() {
            while (m_ptrFirst != m_ptrLast) {
                BoostSharedPtrSmartInt tmp = m_ptrFirst->GetNext();
                m_ptrFirst->Reset();
                m_ptrFirst = tmp;
            }
        }
    };
    ....