尝试访问指向节点的指针时出现分段错误
Segmentation Fault when trying to access pointer to Node
我试图在 Node 结构中启动一个元素,但每当我尝试访问它时,我都会遇到分段错误。我已经在 Stack class 中初始化了节点,但无法在其上插入元素。
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 - 第 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.
}
用nullptr
初始化指针解决
在您的 Stack
class' 构造函数中,您在初始化为任何有意义的内容之前使用 (de-referencing) top_
成员指针。由于它的值可能是某种垃圾,您正试图访问未为您的进程设置的虚拟内存段中的地址;因此你得到一个“分段错误”。
如何避免这种情况?
- 在启用警告的情况下编译您的代码。然后编译器会告诉您有关未初始化值的使用。
有关为什么要启用警告的更多信息,请阅读此 SO 问题:
- 在初始化列表中初始化您的 class' 成员,最好按顺序进行。
关于为什么应该使用初始化列表的讨论,请阅读这个 SO 问题:
Why should I prefer to use member initialization lists?
- 在您的特定 class 中 - 不要尝试在堆栈的顶部元素上设置值,因为它可能不存在。即
top_
的正确初始化是 nullptr
- 你仍然会在尝试取消引用它时崩溃。
您可能还想考虑(这些不是建议,只是想法):
- 使用
std::unique_ptr
而不是原始指针。这会给你异常而不是硬崩溃,而且你永远不会错误地泄漏内存。
- 为堆栈使用 non-list-like 结构(例如更像 std::vector 的东西)。由于除了弹出之外不会迭代堆栈的内容,因此您不必担心迭代器在重新分配时失效。
- 使用
std::stack
(除非这是一个编程练习,在这种情况下没关系)。
我试图在 Node 结构中启动一个元素,但每当我尝试访问它时,我都会遇到分段错误。我已经在 Stack class 中初始化了节点,但无法在其上插入元素。
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 - 第 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.
}
用nullptr
在您的 Stack
class' 构造函数中,您在初始化为任何有意义的内容之前使用 (de-referencing) top_
成员指针。由于它的值可能是某种垃圾,您正试图访问未为您的进程设置的虚拟内存段中的地址;因此你得到一个“分段错误”。
如何避免这种情况?
- 在启用警告的情况下编译您的代码。然后编译器会告诉您有关未初始化值的使用。
有关为什么要启用警告的更多信息,请阅读此 SO 问题:
- 在初始化列表中初始化您的 class' 成员,最好按顺序进行。
关于为什么应该使用初始化列表的讨论,请阅读这个 SO 问题:
Why should I prefer to use member initialization lists? - 在您的特定 class 中 - 不要尝试在堆栈的顶部元素上设置值,因为它可能不存在。即
top_
的正确初始化是nullptr
- 你仍然会在尝试取消引用它时崩溃。
您可能还想考虑(这些不是建议,只是想法):
- 使用
std::unique_ptr
而不是原始指针。这会给你异常而不是硬崩溃,而且你永远不会错误地泄漏内存。 - 为堆栈使用 non-list-like 结构(例如更像 std::vector 的东西)。由于除了弹出之外不会迭代堆栈的内容,因此您不必担心迭代器在重新分配时失效。
- 使用
std::stack
(除非这是一个编程练习,在这种情况下没关系)。