2017-03-04 134 views
1

我正在執行以下算法:這段代碼爲什麼會產生分段錯誤?

1.創建一個空隊列。

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

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) 

我不能推測是爲什麼我得到分割故障的開始功能!?

+0

你用'-g'參數編譯了你的程序嗎?這將添加調試信息,以便gdb可以顯示行號和變量值。 – Paul

+0

是的,我試過...它只是打印分段錯誤(核心轉儲) –

+0

'$ g ++ -Wall -g whatever.c && valgrind ./a.out' –

回答

1

看來您的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++。

+0

thanx很多.. !! 在while循環中包含head-> next-> next確實消除了分段錯誤。 –

+0

@KenilPatel歡迎您,很高興爲您提供幫助。 –

1

-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行,你讓你headhead = head->nextnullptr。在第81行,您訪問head->data,而head == nullptr獲取您的段錯誤。

0

關鍵錯誤是這樣一段代碼:重複

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); 
} 

最後三行而不檢查磁頭是否爲空或不是。在這種情況下,該列表在函數期待它結束並且程序因試圖解引用nullptr而崩潰之前結束。將一個檢查添加到convertListIntoCBT並中止工作,或者您可以構建一個強制在列表中將正確數量的元素插入到函數insertAtHead中的方法。

1

正如其他答案所述,問題在於while聲明。

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

相關問題