使用导致分段错误的类C++中的堆栈实现

Stack implementation in C++ using a class causing segmentation fault

本文关键字:C++ 堆栈 实现 错误 分段      更新时间:2023-10-16

我在C++中为堆栈实现了一些函数。我不确定为什么我会遇到分段错误。现在,我有7个不同的文件:node.h,node.cpp,LL.h,LL.cpp,Stack.h,Stack.cpp和main.cpp我用它来测试LL.cpp和Stack.cpp。如果有人能指导我错误,我将不胜感激。以下是代码:

节点.h :

// node.h
class node { // node class used in the LL (linked list) class
private:
node * next; // Pointer to next node of an LL
int data;    // integer data stored in this node
public:
node(int x, node * n);  // Constructor
~node();                // Destructor
void set_data(int x);   // Change the data of this node
void set_next(node * n);// Change the next pointer of this node
int get_data();         // Access the data of this node
node * get_next();      // Access the next pointer of this node
};  

法学学士 :

// LL.h
#include "node.h"
// Linked list class, used in the Stack class
class LL {
private:
node * head; // pointer to first node
node * tail; // pointer to last node
public:
LL(); // Constructor
~LL(); // Destructor
void prepend(int value); // add a node to the beginning of the LL
int removeHead();        // remove the first node of the LL
void print();            // print the elements of the LL
node * get_head();       // access the pointer to the first node of the LL
};

Stack.h:

// Stack.h
#include "LL.h"
class Stack {
private:
LL * intlist;
public:
Stack();    // Constructor
~Stack();       // Destructor
void push(int value);
int pop();      
int isEmpty();
void Sprint();
};

堆栈.cpp:

// Stack.cpp
#include "Stack.h"
#include <stdio.h>
Stack::Stack() {
}
Stack::~Stack() {
}
int Stack::isEmpty() {
return ( (intlist->get_head()) ==NULL);
}
void Stack::push(int value) {
intlist->prepend(value);
}
int Stack::pop() {
if ( ! isEmpty() ) {
int result=intlist->removeHead();
return result;
}
return -1;
}
void Stack::Sprint() {
intlist->print();
}

这是我用来测试它的主要.cpp:

// main.cpp
#include "Stack.h"
#include <stdio.h>
int main() {
LL a;
a.prepend(3);
a.prepend(4);
a.prepend(5);
a.print();
a.removeHead();
a.print();
Stack sta;
sta.pop();
sta.push(3);
sta.push(4);
sta.push(10);
sta.Sprint();
printf("Popping %dn", sta.pop());
sta.Sprint();
sta.pop();
printf("Stack empty? %dn", sta.isEmpty());
sta.pop();
printf("Stack empty? %dn", sta.isEmpty());
return 0;
}

一段时间以来,我一直在试图找出导致分段错误的原因。任何帮助表示赞赏

这个程序崩溃了,因为你的Stack类从不初始化链表指针(LL * intlist),所以当你检查它是否为空时,它会尝试引用垃圾:

Stack.pop() => Stack.isEmpty() => intlist->isEmpty() => segfault

您可以只将其设置为成员而不是指针(推荐):

class Stack {
private:
LL intlist; // There's no need for it to be a pointer
public:
Stack();    // Constructor
~Stack();       // Destructor
void push(int value);
int pop();      
int isEmpty();
void Sprint();
};

或者,可以在构造函数中初始化它,然后在析构函数中删除它。实际上,只有当成员变量需要成为指针时,才应该这样做;否则,您应该定期存储它。

Stack::Stack() : intlist(new LL()) {       
}
Stack::~Stack() {
delete intlist; 
}

Stack中的指针intlist从未初始化,因此尝试取消引用它会导致段错误(在本例中,它是首次调用sta.pop()时)。

您可以在Stack的构造函数中为intlist分配内存(例如intlist = new LL;),并在完成后将其删除(或改用智能指针)。但在这种情况下,弊大于利。

您最好在Stack中将intlist定义为LL类型的对象,而不是指向它的指针:

class Stack {
private:
LL intlist;
...
};

当然,在使用intlist时,不要忘记将所有箭头运算符(->)替换为点运算符(.)。