【问题标题】:Stack implementation in C++ using a class causing segmentation fault使用导致分段错误的类在 C++ 中实现堆栈
【发布时间】:2019-08-07 00:58:07
【问题描述】:

我已经在 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:

// 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
};

堆栈.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();
}

这是我用来测试它的 main.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 %d\n", sta.pop());
        sta.Sprint();

        sta.pop();
    printf("Stack empty? %d\n", sta.isEmpty());

        sta.pop();
        printf("Stack empty? %d\n", sta.isEmpty());
    return 0;
}

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

【问题讨论】:

  • 找出程序崩溃原因的最佳方法是从程序中删除所有未崩溃的内容并检查剩余的内容。有关如何执行此操作的建议,请参阅 minimal reproducible example
  • @user4581301 实际上,确定程序崩溃原因的最佳方法是使用调试器运行它,该调试器会因错误而中断。所以你应该尝试这样做。我也有点相信它会崩溃,因为你在实际上拥有任何内存的指针上调用 delete 。如果你没有调用 new,你不应该调用 delete。此外,您应该努力改进您的编码风格并使用 C++ 的东西而不是 C 的东西,比如 iostream 和 nullptr。
  • 我确实尝试注释掉所有内容,例如 sta.pop()、sta.push、sta.print(),但我仍然遇到 Seg 错误。我认为错误可能出现在“Stack sta”行的声明中?但不确定为什么会这样。无论如何,谢谢你的提示
  • 我对 new/delete 的看法很糟糕,我看了一眼,并没有看到你实际上在调用 new。
  • @john 由您决定,但就其本身而言,它可以具有任何价值。但是,我想第一个问题是:指针真的有必要吗?

标签: c++ class methods segmentation-fault stack


【解决方案1】:

这个程序崩溃了,因为你的 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; 
}

【讨论】:

  • 感谢您的建议!我相应地更新了我的答案。
  • 绝对!如果您还有任何疑问或问题,请发表评论!
【解决方案2】:

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

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

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

class Stack {
    private:
        LL intlist;

    ...
};

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2021-01-17
    • 2013-10-05
    相关资源
    最近更新 更多