簡體   English   中英

為什么這段代碼會出現分段錯誤?

[英]Why does this code gives segmentation fault?

我正在實現以下算法:

1.創建一個空隊列。

2.以列表的形式創建列表的第一個節點,並將其排入隊列。

3.直到我們到達列表的末尾,執行以下操作。

  • 將一個節點從隊列中出列。 這是當前的父母。

  • 遍歷列表中的兩個節點,將它們添加為當前父節點的子節點。

  • 將兩個節點排入隊列。


#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <queue>
using namespace std;

struct Node{
    int data;
    struct Node* next;
};

typedef struct Node* NODE;

NODE createNode(int data){
    NODE newNode = (NODE) malloc (sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return (newNode);
}

void insertAtEnd(NODE* head, int data){
    NODE newNode = createNode(data);
    if(*head == NULL){
        *head = newNode;
        return ;
    }

    NODE temp = *head;
    while(temp->next){
        temp = temp->next;
    }
    temp->next = newNode;
    newNode->next = NULL;
    return;
}


struct tree_node{
    int data;
    struct tree_node* left;
    struct tree_node* right;
};

typedef struct tree_node* T_NODE;

T_NODE createTreeNode(int data){
    T_NODE newNode = new tree_node;
    newNode->right = NULL;
    newNode->left = NULL;
    newNode->data = data;
    return newNode;
}

void inorderTraversal(){}


T_NODE convertListIntoCBT(NODE head){


    T_NODE root;

    if(head){
        queue<T_NODE>q;
        root=createTreeNode(head->data);

        if(!root){
            cout << "Error creating root"<<endl;
            exit(-1);
        }
        q.push(root);

        T_NODE temp=NULL , parent=NULL;
        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);
        }

        return root;
    }
}

int main(){

    NODE head = NULL;
    insertAtEnd(&head,36);
    insertAtEnd(&head,30);
    insertAtEnd(&head,25);
    insertAtEnd(&head,15);
    insertAtEnd(&head,12);
    insertAtEnd(&head,10);

    //convert the given linked list into complete binary tree
    T_NODE new_root = convertListIntoCBT(head);

    return 0;
}

我嘗試使用gdb進行調試,得到以下結果:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400e5a in convertListIntoCBT(Node*) ()
(gdb) backtrace
0  0x0000000000400e5a in convertListIntoCBT(Node*) ()
1  0x0000000000400fa2 in main ()
(gdb) 

我無法理解為什么我在函數的開頭出現了分段錯誤!?

使用-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行,你讓你headnullptrhead = head->next 在第81行中,您訪問head->datahead == nullptr獲取您的段錯誤。

看來你的while(head->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);
        }
    }

同樣在評論中建議,不要將C風格與C ++風格混合,選擇一種語言並嘗試堅持下去。 我在這里談論使用malloctypedef struct ,雖然它們編譯,但它們不是“通常的”C ++。

正如其他答案所述,問題在於while語句。

函數convertListIntoCBT另一個問題是,如果head == nullptr它沒有return

關鍵錯誤是這段代碼:

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是否為NULL。 在這種情況下,列表在函數期望之前結束,並且程序通過嘗試取消引用nullptr而崩潰。 添加對convertListIntoCBT和中止工作的檢查,或者您可以構建一種方法來強制將列表中正確數量的元素添加到函數insertAtHead中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM