2017-03-04 139 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

相关问题