如何修复 C++ 中的“分段错误”错误

Posted

技术标签:

【中文标题】如何修复 C++ 中的“分段错误”错误【英文标题】:How to fix 'Segmentation fault' error in c++ 【发布时间】:2019-08-30 03:02:35 【问题描述】:

我正在尝试学习如何使用 gdb 调试器来修复此示例代码。单步执行调试器时,我可以看到“mylist[i]->val = i;”这一行正在引发分段错误。

我想我明白什么是分段错误,但我不明白这条线是如何导致它的。我需要为 mylist 向量分配内存吗?我该怎么做?我以为向量已经在 main() 中初始化并准备好了,但我不太确定。

我尝试对 mylist 向量中的每个节点使用“new”,但这给了我一个编译错误。

node* mylist[i] = new node; //what I tried
mylist[i]->val = i; 
mylist[i]->next = NULL;   

//error message
error: array must be initialized with a brace-enclosed initializer
node* mylist[i] = new node;

我的代码

class node

public:
    int val;
    node* next;
;

void create_LL(vector<node*>& mylist, int node_num)

    mylist.assign(node_num, NULL);

//create a set of nodes
    for (int i = 0; i < node_num; i++)
    
        mylist[i]->val = i; //error happens here
        mylist[i]->next = NULL;
    

... (relevant section of main() below)

int main(int argc, char ** argv)

    const int NODE_NUM = 3;
    vector<node*> mylist;
    create_LL(mylist, NODE_NUM);

显示的实际错误是“Segmentation fault (core dumped)”

当我在它显示的错误行之前打印 mylist 时

$1 = std::vector of length 3, capacity 3 = 0x0, 0x0, 0x0

我还在学习 c++,所以我可能会遗漏一些非常基本的东西。 我真的很感激任何帮助。谢谢!

【问题讨论】:

您需要为节点分配内存。您只是在向量中添加了一堆空指针。如果您在分配内存时遇到问题,最好将该尝试与完整的错误消息一起发布。还不清楚您要尝试做什么。链表节点的向量有点奇怪。 我想我不明白如何为节点分配内存。我尝试添加这个“node* mylist[i] = new node;”在错误线上方,但我得到数组必须初始化错误 你在哪里填充向量? 向量永远不会被填充,它在 main() 中初始化,然后立即在 create_LL() 中调用。它应该只包含 3 个节点,其键分配给 i (0, 1, 2) 初始化向量为vector&lt;node*&gt; mylist(NODE_NUM, new node()) 【参考方案1】:

对于初学者,最好将变量隐藏在 class 中。如果您不打算这样做,约定是使用struct。在这种情况下,提供一些构造函数也是一种很好的做法,并且可能带有默认值:

class node

    int val;
    node* next;
public:
    node(int v= 0, node* n= nullptr) : val(v), next(n) 
;

注意使用nullptr 而不是NULL。在 c++ 中使用后者是一种不好的做法。

问题是如果std::vector 上的位置尚未分配,您将无法使用它们。当您执行mylist[i]-&gt;val = i; 时,您就处于未定义行为的领域。

您需要先将push_back()emplace_back() 转换为std::vector。所以size() 会随着将您的数据放在vector 的末尾(back)而增长。您也可以使用其他方法,例如reserve()。虽然push_back()node* 元素推送到您的列表中,但emplace_back() 将在没有副本的情况下将它们构造到位(与原始指针没有区别,但您可以使用vector&lt;node&gt; 而不是vector&lt;node*&gt;,这更简单。

// create a set of nodes
void create_LL(vector<node>& mylist, int node_num)

    for (int i = 0; i < node_num; i++) 
        mylist.emplace_back(i, nullptr); // calls node::node(i, nullptr) and inserts it at the end of the vector
    

// create a set of nodes
void create_LL(vector<node*>& mylist, int node_num)

    for (int i = 0; i < node_num; i++) 
        mylist.emplace_back(new node(i, nullptr));
    

【讨论】:

如果您在答案正文中写了一些解释,而不仅仅是代码中的 cmets,这个答案会更好。它看起来像一个纯代码的答案。它至少应该有一个介绍性声明,说明问题是什么以及您的解决方案如何解决问题。

以上是关于如何修复 C++ 中的“分段错误”错误的主要内容,如果未能解决你的问题,请参考以下文章

带有向量和字符串的 C++ 分段错误

C++ 中的分段错误(特征库)

C++:当我添加看似无关的代码行时,分段错误消失了

如何删除我的 C++ 代码中的分段错误?

C++ 分段错误 OpenCV

分段错误:在 C++ 中弹出向量时出现 11