c++ - 包含多个对象的手写单链表中的分段错误
问题描述
我正在处理自定义编写的单链表,其元素是指向对象的智能指针。问题是,在列表中成功插入一定数量的元素(例如 50000)后,当列表超出范围并且元素开始被逐个破坏(通过智能指针)时,程序会因分段错误而崩溃。成功创建了 50000 个元素,但每次销毁 43256(例如)对象时,程序都会崩溃。
注意:处理少量对象时——5000、10000、20000……——完全没有问题。
我们使用 C++98 标准和 Boost 1.55.0 C++ 库。
该程序发生在 Red Hat 上,但我也在 Ubuntu 本地尝试过——同样的交易。我为实验尝试的是使用 std::list、std::vector、boost::container::slist 而不是编写的单链表,问题就消失了。但我真的很想了解问题出在哪里。
这是重现该问题的示例代码:
#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;
}
为了构建项目,我使用 CMakeLists.txt 如下:
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} )
在此先感谢,我真的很困惑为什么会发生崩溃,我已经处理了 1-2 周了......
解决方案
正如Botje 所怀疑的那样,您的程序由于堆栈溢出而崩溃。您可以通过在列表析构函数中一个接一个地显式释放列表项来避免这种情况。
...
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;
}
}
};
....
推荐阅读
- java - 下载后自动打开 PDF
- docker - 无法连接到从 docker 映像创建的本地数据库
- angular - 如何使用 ngOnInit 测试 http 调用的承诺所期望的第二个值
- python - 我们如何从数据框中获取最小日期,每年和每个 ID?
- apache-spark - 根据先前的值和行 Pyspark 填充列
- javascript - HLS video quality selector in React.js
- css - typekit 返回状态码 412 前置条件失败
- javascript - 如何手动更改 Parcel 中的文件名?
- python - 使用 Pandas 数据框覆盖现有工作表上的现有 Excel 数据?
- json - 从 Scala 中 json 的字符串表示形式的任何键值中获取值(使用 scala.util.parsing.json)