C++ main()函数的意外返回值
我正在使用双链接列表。每个函数都运行良好,但在main()的末尾,它会暂停几秒钟并返回意外的随机值 起初,我认为这是由report()函数引起的,因此我在末尾又添加了一个add()函数,但没有修复任何问题。我怀疑这是内存释放问题,但我看不出某个对象在哪里被预释放。 (使用代码::Blocks 17.12编译) 这是我的.cpp文件(一体机):C++ main()函数的意外返回值,c++,linked-list,C++,Linked List,我正在使用双链接列表。每个函数都运行良好,但在main()的末尾,它会暂停几秒钟并返回意外的随机值 起初,我认为这是由report()函数引起的,因此我在末尾又添加了一个add()函数,但没有修复任何问题。我怀疑这是内存释放问题,但我看不出某个对象在哪里被预释放。 (使用代码::Blocks 17.12编译) 这是我的.cpp文件(一体机): #包括 使用名称空间std; 类型定义结构元素{ 元素(){ 数据=0; next=0; prev=0; } ~element(){ 删除下一步; 删除上
#包括
使用名称空间std;
类型定义结构元素{
元素(){
数据=0;
next=0;
prev=0;
}
~element(){
删除下一步;
删除上一页;
cout-prev;
}
删除尾部;
cout数据;
如果(ls.head==0){//empty
ls.head=新元素;
ls.水头=温度;
}否则{
如果(ls.tail==0){//1-项列表
ls.tail=新元素;
ls.tail=温度;
ls.head->next=ls.tail;
ls.tail->prev=ls.head;
}
否则{
temp->prev=ls.tail;
ls.tail->next=温度;
ls.tail=温度;
}
}
}
作废报告(){
如果(ls.head==0)不能第一点:元素将被类doublylinkedlist
解除分配,因此解除类元素中的元素将导致双重解除分配。
因此,应该从lass元素的析构函数中删除两条delete
语句
~element(){
/* remove them */
//delete next;
//delete prev;
cout << "element destructed" << endl;
}
最后一个元素将由delete tail;
释放,因此此代码看起来很复杂,但应该可以
额外要点:这些代码段
ls.head = new elem;
ls.head = temp;
及
正在通过分配元素并立即丢弃它们而导致内存泄漏。
您应该删除额外的分配
/* remove this */
//ls.head = new elem;
ls.head = temp;
及
除非您使用的是std::shared_ptr
或类似的构造,否则每个对象都需要有另一个对象,即它的所有者并负责解除分配它。您的代码需要有明确的所有权转移语义(例如,函数createNode()
希望其调用者破坏节点)
在您的代码中,列表和每个元素都会删除节点。这意味着所有内容都会被删除两次(或更多)。在您的特定情况下,这是销毁doublylinkedlist
的事件序列:
双链接列表
删除其第一个元素
第一个元素的析构函数删除其前一个元素,该值为null,因此无效
第一个元素的析构函数删除下一个元素(第二个元素)
第二个元素的析构函数删除其前一个元素(第一个元素)
第一个元素的析构函数删除其前一个元素,该值为null,因此无效
第一个元素的析构函数删除下一个元素(第二个元素)
这个无限循环最终会导致堆栈溢出。请注意,这并不能保证是事件的精确序列,因为删除一个对象两次是未定义的行为,因此可能会发生任何事情
简单的修复方法是删除元素
析构函数,并让列表负责所有元素的生存期。
您还应该修改doublylinkedlist
析构函数,因为它将尝试取消对最后一个元素上的空指针的引用,您也不需要删除tail
,因为它应该已经被删除。例如:
~doublylinkedlist(){
while(head!=0) {
auto temp = head;
head = head->next;
delete temp;
}
}
您还应确保遵守)。一种方法是使用智能指针,例如使用unique\ptr
s您的代码可能如下所示:
#include <iostream>
#include <memory>
using namespace std;
typedef struct element {
element() {
data = 0;
next = nullptr;
prev = nullptr;
}
~element() {
cout << "element destructed" << endl;
}
int data;
std::unique_ptr< element > next;
element* prev;
} elem;
typedef struct doublylinkedlist {
doublylinkedlist() {
head = 0; tail = 0;
}
~doublylinkedlist() {
std::cout << "list destructed\n";
}
std::unique_ptr< elem > head;
elem* tail;
} doublyll;
doublyll ls;
void add() {
std::unique_ptr<elem> temp(new elem());
cout << "Enter an integer: ";
cin >> temp->data;
if (ls.head == nullptr) {//empty
ls.head = std::move(temp);
}
else {
if (ls.tail == nullptr) { //1-item list
ls.head->next = std::move(temp);
ls.tail = ls.head->next.get();
ls.tail->prev = ls.head.get();
}
else {
temp->prev = ls.tail;
ls.tail->next = std::move(temp);
ls.tail = ls.tail->next.get();
}
}
}
void report() {
if (ls.head == 0) cout << "List is empty!" << endl;
else {
elem *temp = ls.head.get();
do {
cout << temp->data << endl;
temp = temp->next.get();
} while (temp != 0);
}
}
int main() {
report();
add();
add();
add();
report();
add();
return 0;
}
一些元素将被双链接列表
和元素
多次删除,但应该还有一些问题,因为从元素
析构函数中删除删除
语句并没有消除分段错误。ls.head=new elem;ls.head=temp;
Oh,内存泄漏。。。(同样的错误也使用了<代码> ls。尾<代码>),这不解决这个问题,但是在C++中,你不必做那个<代码> TyPufFr.{…} elm;< /Cord>舞曲。<代码> StuttELEM{};工作很好。或者只使用<代码> Stutt元素{}…;
忘记缩写。0xc0000fd
不是一个随机数,它意味着有一个堆栈overflow@AlanBirtles非常感谢您告诉我这一点。结果表明,返回值0xc0000fd
是由于访问空指针引起的,这是由于我在doublyll解构器中的哑代码:delete head->prev;
造成的。关于另外一点,我是这样想的:temp是在add()函数中声明的,因此在退出add()函数之前,~elem()解构器会解构它,所以我分配了ls.head和ls.tail,因为它们的作用域是全局的。我弄错了吗?@xceededadd()
函数在元素
类之外,因此~elem()
解构器不会影响add()
函数中的局部变量。指针temp
将在退出add()时释放
函数,但指针分配给该函数的空间在该时间不会被释放,ls.head
和ls.tail
已作为ls
的一部分分配给ls.head=new elem;
不是分配ls.head
而是分配另一个空间并将其位置分配给ls.head
。等等,我f A:“ls.head
指向temp
”,B:“temp
在退出add()
”时被删除,C:“删除对象后取消引用指针的程序可能会产生不可预测的结果或崩溃”(),那么为什么我的程序仍然工作?temp
在退出add()时被删除)
,但是temp
所指向的内容(通过新元素创建的内容)不会被删除
/* remove this */
//ls.head = new elem;
ls.head = temp;
/* remove this */
//ls.tail = new elem;
ls.tail = temp;
~doublylinkedlist(){
while(head!=0) {
auto temp = head;
head = head->next;
delete temp;
}
}
#include <iostream>
#include <memory>
using namespace std;
typedef struct element {
element() {
data = 0;
next = nullptr;
prev = nullptr;
}
~element() {
cout << "element destructed" << endl;
}
int data;
std::unique_ptr< element > next;
element* prev;
} elem;
typedef struct doublylinkedlist {
doublylinkedlist() {
head = 0; tail = 0;
}
~doublylinkedlist() {
std::cout << "list destructed\n";
}
std::unique_ptr< elem > head;
elem* tail;
} doublyll;
doublyll ls;
void add() {
std::unique_ptr<elem> temp(new elem());
cout << "Enter an integer: ";
cin >> temp->data;
if (ls.head == nullptr) {//empty
ls.head = std::move(temp);
}
else {
if (ls.tail == nullptr) { //1-item list
ls.head->next = std::move(temp);
ls.tail = ls.head->next.get();
ls.tail->prev = ls.head.get();
}
else {
temp->prev = ls.tail;
ls.tail->next = std::move(temp);
ls.tail = ls.tail->next.get();
}
}
}
void report() {
if (ls.head == 0) cout << "List is empty!" << endl;
else {
elem *temp = ls.head.get();
do {
cout << temp->data << endl;
temp = temp->next.get();
} while (temp != 0);
}
}
int main() {
report();
add();
add();
add();
report();
add();
return 0;
}
void add() {
std::unique_ptr<elem> temp(new elem());
cout << "Enter an integer: ";
cin >> temp->data;
if (!cin || temp->data > 100) {
cout << "invalid input value\n";
return; // temp is automatically deleted here
}
...
}