1

I'm trying to initiate an element inside a Node struct but whenever I try to access it I get a Segmentation Fault. I have initialized the Node inside my Stack class but cannot insert an element on it.

Stack.h

#ifndef QUEUE_H
#define QUEUE_H

struct Node;

// Pilha de números inteiros.
class Stack {
public:
    // Representa uma exceção que ocorre quando a pilha está vazia.
    class EmptyException {};

    // Constrói uma pilha vazia.
    Stack();

    // Insere um elemento no topo da pilha.
    void push(unsigned elem);

    // Retorna o elemento no topo da pilha.
    // Lança EmptyException caso a pilha esteja vazia.
    unsigned top() const;

    // Remove o elemento no topo da pilha.
    // Lança EmptyException caso a pilha esteja vazia.
    void pop();

    // Retorna o número de elementos na pilha.
    unsigned count() const;
private:
    Node* _top{};
    unsigned _count;
};

#endif

Stack.cpp - The segmentation fault is occurring on line 10

#include "Stack.h"

struct Node {
    unsigned elem{};
    Node * next{};
};

Stack::Stack() {
    this->_count = 0;
    this->_top->elem = 0; // This is where the segmentation fault is occurring
}

void Stack::push(unsigned elem) {
    this->_top->elem = elem;
    this->_count++;
}

void Stack::pop() {
    // TODO.
}

unsigned Stack::top() const {
    return 0;
}

unsigned Stack::count() const {
    return 0;  // TODO.
}

Screenshot of lines of code and variables

cigien
  • 57,834
  • 11
  • 73
  • 112
Braganca
  • 106
  • 1
  • 8
  • 1
    You shouldn't post information using screenshots. Enter the relevant text (e.g. a stack trace or variable values). – einpoklum Oct 17 '20 at 20:32

2 Answers2

2

In your Stack class' constructor, you are using (de-referencing) the top_ member pointer before having initialized to anything meaningful. Since its value is likely some kind of junk, you're trying to access an address in a virtual memory segment not set up for your process; thus you get a "Segmentation Fault".

What to do to avoid this?

  1. Compile your code with warnings enabled. The compiler would then have told you about the use of an uninitialized value.
    For more information on why you should enable warnings, please read this SO question:
    Why should I always enable compiler warnings?
  2. Initialize your class' members, preferably in order, in an initialization list.
    For a discussion of why you should use initialization lists, please read this SO question:
    Why should I prefer to use member initialization lists?
  3. In your specific class - don't try to set a value on the top element of the stack when it may not exist. i.e. the proper initialization of top_ is to nullptr - you would have still crashed trying to dereference it.

You may also want to consider (these aren't recommendations, just ideas):

  1. Using std::unique_ptr's instead of raw pointers. That will give you exceptions rather than hard crashes, plus you'll never leak memory by mistake.
  2. Using a non-list-like structure for the stack (e.g. something more like an std::vector). Since you don't iterate the contents of the stack except by popping, you shouldn't be worried about iterator invalidation upon reallocation.
  3. Using std::stack (unless this is a programming exercise, in which case nevermind).
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Thank you for your inputs @einpoklum. It was an exercise so you had to do it as a linked list. I am fairly new to C++ so I will absolutely read about your suggestions. Thank you for taking the time – Braganca Oct 18 '20 at 21:08
  • 1
    @Braganca: If you want to thank me - please tell your _teachers/teaching assistants_ that they should encourage all students to compile with warnings turned on. – einpoklum Oct 18 '20 at 21:28
0

Solved by initializing the pointer with nullptr

Braganca
  • 106
  • 1
  • 8