简体   繁体   English

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

[英]Stack implementation in C++ using a class causing segmentation fault

I have implemented some functions for a Stack in C++. 我已经在C ++中实现了一些Stack功能。 I am unsure as to why I am getting a segmentation fault. 我不确定为什么会出现细分错误。 Right now, I have 7 different files: node.h, node.cpp, LL.h, LL.cpp, Stack.h, Stack.cpp and main.cpp which I am using to test LL.cpp and Stack.cpp. 现在,我有7个不同的文件:node.h,node.cpp,LL.h,LL.cpp,Stack.h,Stack.cpp和main.cpp,这些文件用于测试LL.cpp和Stack.cpp。 If anyone could direct me to the error, I would really appreciate it. 如果有人可以引导我指出错误,我将不胜感激。 Here are the codes: 以下是代码:

node.h : node.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:

// 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:

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

Stack.cpp: Stack.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();
}

And here is the main.cpp that I am using to test it: 这是我用来测试的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;
}

I have been trying to find what's causing the segmentation fault for a while. 我一直在尝试查找导致分段错误的原因。 Any help appreciated 任何帮助表示赞赏

This program is crashing because your Stack class never initializes the Linked List pointer ( LL * intlist ), so when you check if it's empty it tries referencing garbage: 该程序崩溃是因为您的Stack类从不初始化链接列表指针( LL * intlist ),因此当您检查它是否为空时,它将尝试引用垃圾:

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

You could just make it a member instead of a pointer (recommended): 您可以使它成为成员而不是指针(推荐):

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

Alternatively, you could initialize it in the constructor and delete it in the destructor. 另外,您可以在构造函数中对其进行初始化,而在析构函数中将其删除。 You should really only do this when a member variable needs to be a pointer; 实际上,只有在成员变量需要为指针时才应该这样做。 otherwise you should just store it regularly. 否则,您应该定期存储它。

Stack::Stack() : intlist(new LL()) {       
}

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

Pointer intlist in Stack is never initialized, so attempting to dereference it caused your segfault (in this case, it was when sta.pop() was first called). Stack指针intlist从未初始化,因此尝试对其进行取消引用会导致您的段错误(在这种情况下,是第一次调用sta.pop()时)。

You could allocate memory for intlist in Stack 's constructor (eg intlist = new LL; ) and delete it when you're done (or use a smart pointer instead). 您可以在Stack的构造函数中为intlist分配内存(例如, intlist = new LL; ),并在完成intlist = new LL;其删除(或使用智能指针)。 But in this case that'll do more harm than good. 但是在这种情况下,弊大于利。

You're likely better off defining intlist as an object of type LL , not a pointer to it, in Stack : 您最好在Stack intlist定义为LL类型的对象,而不是指向它的指针:

class Stack {
    private:
        LL intlist;

    ...
};

Of course, don't forget to replace all arrow operators ( -> ) with dot operators ( . ) when working with intlist . 当然,在使用intlist时,请不要忘记将所有箭头运算符( -> )替换为点运算符( . )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM