C++ 为什么这个代码会给出分段错误?

C++ 为什么这个代码会给出分段错误?,c++,segmentation-fault,C++,Segmentation Fault,我正在实现以下算法: 1.创建一个空队列 2.将列表的第一个节点设为根节点,并将其排入队列 3.在列表结束之前,请执行以下操作 从队列中退出一个节点。这是当前父级 遍历列表中的两个节点,将它们添加为当前父节点的子节点 将两个节点加入队列 我无法理解为什么我在函数开始时出现分段错误 使用-g构建时,您应该具有可调试二进制文件: % lldb 1 (lldb) target create "1" Current executable set to '1' (x86_64). (lldb) r

我正在实现以下算法:

1.创建一个空队列

2.将列表的第一个节点设为根节点,并将其排入队列

3.在列表结束之前,请执行以下操作

  • 从队列中退出一个节点。这是当前父级

  • 遍历列表中的两个节点,将它们添加为当前父节点的子节点

  • 将两个节点加入队列



我无法理解为什么我在函数开始时出现分段错误

使用
-g
构建时,您应该具有可调试二进制文件:

% lldb 1
(lldb) target create "1"
Current executable set to '1' (x86_64).
(lldb) r
Process 44386 launched: '/Users/paul/src/cpp/1' (x86_64)
Process 44386 stopped
* thread #1: tid = 0xb6153, 0x0000000100001217 1`convertListIntoCBT(head=0x0000000000000000) + 887 at 1.cpp:81, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000100001217 1`convertListIntoCBT(head=0x0000000000000000) + 887 at 1.cpp:81
   78                                   parent->left = createTreeNode(head->data);
   79                                   q.push(parent->left);
   80                                   head = head->next;
-> 81                                   parent->right = createTreeNode(head->data);
   82                                   q.push(parent->right);
   83                           }
   84
(lldb) bt
* thread #1: tid = 0xb6153, 0x0000000100001217 1`convertListIntoCBT(head=0x0000000000000000) + 887 at 1.cpp:81, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000100001217 1`convertListIntoCBT(head=0x0000000000000000) + 887 at 1.cpp:81
    frame #1: 0x0000000100001484 1`main + 116 at 1.cpp:100
    frame #2: 0x00007fff9cffe5ad libdyld.dylib`start + 1
    frame #3: 0x00007fff9cffe5ad libdyld.dylib`start + 1
(lldb) p parent
(T_NODE) $0 = 0x0000000100300320
(lldb) p head
(NODE) $1 = 0x0000000000000000

因此,在第80行中,通过执行
head=head->next
使您
head
成为
nullptr
。在第81行中,您访问
head->data
,而
head==nullptr
获取您的segfault。

似乎在
while(head->next)
循环中缺少一些检查。我认为您应该对next和next-to-next进行检查,因为您在循环中同时使用了这两个选项:

while(head->next && head->next->next)
{
    //...
}
    while(head->next){
        temp = q.front();
        q.pop();
        parent = temp;
        head = head->next;
        parent->left = createTreeNode(head->data);
        q.push(parent->left);

        if(head->next) // <-- check again here
        {
            head = head->next;
            parent->right = createTreeNode(head->data);
            q.push(parent->right);
        }
    }
或者在循环内第二次前进之前再次检查:

while(head->next && head->next->next)
{
    //...
}
    while(head->next){
        temp = q.front();
        q.pop();
        parent = temp;
        head = head->next;
        parent->left = createTreeNode(head->data);
        q.push(parent->left);

        if(head->next) // <-- check again here
        {
            head = head->next;
            parent->right = createTreeNode(head->data);
            q.push(parent->right);
        }
    }
while(head->next){
温度=q.前();
q、 pop();
父母=临时;
头部=头部->下一步;
父->左=创建树节点(头->数据);
q、 推送(父级->左);
if(head->next)//next;
父->右=创建树节点(头->数据);
q、 推送(父->右);
}
}

也如评论中所建议的,不要将C风格与C++风格混合,选择一种语言并尝试坚持下去。我在这里谈到的是使用<代码> MalcC < /C> >代码> TyPufFrase,虽然它们编译,但它们不是“通常”C++。

< P>
while(head->next){
    temp = q.front();
    q.pop();
    parent = temp;
    head = head->next;
    parent->left = createTreeNode(head->data);
    q.push(parent->left);
    head = head->next;
    parent->right = createTreeNode(head->data);
    q.push(parent->right);
}

重复最后三行,不检查head是否为空。在这种情况下,该列表在函数期望它结束之前结束,程序试图取消对nullptr的引用而崩溃。向convertListIntoCBT添加检查并中止工作,或者您可以构建一种方法来强制将列表中正确数量的元素添加到函数Insertthead中。

正如其他答案所述,问题在于
while
语句


函数
convertListIntoCBT
中的另一个问题是,如果
head==nullptr

使用
-g
参数编译程序了吗?这将添加调试信息,以便gdb可以显示行号和变量值。是的,我尝试过…它只打印分段错误(内核转储)
$g++-Wall-g whatever.c&&valgrind./a.out
@KenilPatel In
convertListIntoCBT
,如果
head
为空,则不会返回值。这是未定义的行为。你的编译器应该警告你这一点。另外,你为什么在程序中混用
malloc
new
?因为这是C++,所以使用<代码>新< /代码>。在while循环中包含head->next->next确实消除了分段错误。。