C++:进程结束,退出代码为 139(被信号 11 中断:SIGSEGV)
C++: Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
我用 C++ 中的列表进行了测试,并为它创建了一个最简单的 class。我删除了一些检查和其他方法以仅显示重点。
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.00)
PROJECT(test)
SET(CMAKE_CXX_STANDARD 98)
ADD_EXECUTABLE(test main.cpp CList.h)
CList.h
#ifndef CLIST_H
#define CLIST_H
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <stdint.h>
struct CItem {
size_t data;
CItem *prev;
CItem *next;
CItem(size_t item);
~CItem();
};
CItem::CItem(size_t item) {
this->data = item;
this->prev = NULL;
this->next = NULL;
}
CItem::~CItem() {
delete this->next;
}
class CList {
CItem *first;
CItem *last;
size_t length;
public:
CList();
~CList();
CList &add(size_t data);
};
CList::CList() {
this->first = NULL;
this->last = NULL;
this->length = 0;
}
CList::~CList() {
delete this->first;
}
CList &CList::add(size_t data) {
CItem *item = new CItem(data);
if (!item) {
fputs("Not enough memory", stderr);
exit(1);
}
if (!this->length) {
this->first = this->last = item;
} else {
item->prev = this->last;
this->last->next = item;
this->last = this->last->next;
}
this->length++;
return *this;
}
#endif //CLIST_H
main.cpp
#include "CList.h"
int main() {
CList list;
for (size_t i = 0; i < 1000000; i++) {
list.add(i);
}
return 0;
}
如您所见,CList析构函数调用了第一项的CItem析构函数,递归调用了其他项的析构函数。
为了测试代码,我向列表中添加了 1,000,000 个项目。代码应该在存在时释放内存。但是我在 CItem 析构函数(不是第一项)上收到 SIGSEGV 错误。
当我只添加 100,000 个项目时没有错误。出现大量元素的错误。
再次强调,这不是真正的代码,只是一些测试。我知道我至少可以使用 std::
classes 来代替。我尝试使用本机类型尽可能简单地做到这一点。
您的代码造成堆栈溢出,因为它递归地从前一个节点的析构函数中删除下一个节点。当你有一百万个元素时,这会导致一百万次递归。在大多数平台上,堆栈大小限制在 1-8MB 左右,即使每个函数调用仅使用 8 个字节的堆栈(通常会更多)也会导致一百万个元素溢出。
您应该 non-recursively 删除 CList
析构函数中的项目:
CList::~CList() {
CItem* item = this->first;
while (item) {
CItem* temp = item;
item = item->next;
delete temp;
}
}
我用 C++ 中的列表进行了测试,并为它创建了一个最简单的 class。我删除了一些检查和其他方法以仅显示重点。
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.00)
PROJECT(test)
SET(CMAKE_CXX_STANDARD 98)
ADD_EXECUTABLE(test main.cpp CList.h)
CList.h
#ifndef CLIST_H
#define CLIST_H
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <stdint.h>
struct CItem {
size_t data;
CItem *prev;
CItem *next;
CItem(size_t item);
~CItem();
};
CItem::CItem(size_t item) {
this->data = item;
this->prev = NULL;
this->next = NULL;
}
CItem::~CItem() {
delete this->next;
}
class CList {
CItem *first;
CItem *last;
size_t length;
public:
CList();
~CList();
CList &add(size_t data);
};
CList::CList() {
this->first = NULL;
this->last = NULL;
this->length = 0;
}
CList::~CList() {
delete this->first;
}
CList &CList::add(size_t data) {
CItem *item = new CItem(data);
if (!item) {
fputs("Not enough memory", stderr);
exit(1);
}
if (!this->length) {
this->first = this->last = item;
} else {
item->prev = this->last;
this->last->next = item;
this->last = this->last->next;
}
this->length++;
return *this;
}
#endif //CLIST_H
main.cpp
#include "CList.h"
int main() {
CList list;
for (size_t i = 0; i < 1000000; i++) {
list.add(i);
}
return 0;
}
如您所见,CList析构函数调用了第一项的CItem析构函数,递归调用了其他项的析构函数。
为了测试代码,我向列表中添加了 1,000,000 个项目。代码应该在存在时释放内存。但是我在 CItem 析构函数(不是第一项)上收到 SIGSEGV 错误。 当我只添加 100,000 个项目时没有错误。出现大量元素的错误。
再次强调,这不是真正的代码,只是一些测试。我知道我至少可以使用 std::
classes 来代替。我尝试使用本机类型尽可能简单地做到这一点。
您的代码造成堆栈溢出,因为它递归地从前一个节点的析构函数中删除下一个节点。当你有一百万个元素时,这会导致一百万次递归。在大多数平台上,堆栈大小限制在 1-8MB 左右,即使每个函数调用仅使用 8 个字节的堆栈(通常会更多)也会导致一百万个元素溢出。
您应该 non-recursively 删除 CList
析构函数中的项目:
CList::~CList() {
CItem* item = this->first;
while (item) {
CItem* temp = item;
item = item->next;
delete temp;
}
}