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

时间:2019-08-30 03:02:35

标签: c++ vector linked-list segmentation-fault

我正在尝试学习如何使用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);

显示的实际错误是“分段错误(核心已转储)”

当我在错误行之前打印我的列表时,

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

我仍在学习c ++,因此可能会缺少一些真正的基础知识。 我真的很感谢您的帮助。谢谢!

1 个答案:

答案 0 :(得分: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]->val = i;时,您就处在行为不确定的领域。

您需要先将push_back()emplace_back()插入std::vector。因此,size()的增长是因为它将数据放在back的末尾(vector)。您还可以使用其他方法,例如reserve()。虽然push_back()node*元素推送到列表中,但是emplace_back()会在没有副本的情况下将它们构造在适当的位置(与原始指针没有区别,但是您可以使用vector<node>而不是{ {1}}更简单。

vector<node*>

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