2015-12-11 29 views
0

我已经通过gdb在代码中发现了这条代码以进行seg错误。然而,我似乎无法明白为什么?在发生seg故障之前,它将运行6/7次。 Temp是包含频率(int)的链接列表中的一个节点,我使用它来在升序链接列表中查找位置以插入新节点。为什么在构建二叉树时进行这种分割?

while (ind == 0 && temp != NULL) 
{ 
    temp = temp -> next; 
    if (temp -> frequency > parent_node -> frequency) /*<--- SEG FAULT HERE */ 
    { 
     parent_node -> next = temp -> next; /* parent points at higher freq node */ 
     temp -> next = parent_node; /* parent node is temp next */ 
     ind = 1; 
    } 
    if (temp -> next == NULL) 
    { 
     temp -> next = parent_node; 
     ind = 1;   
    } 
} 
+1

'温度=温度 - >下; ':'temp'变成'NULL' – BLUEPIXY

+0

http://ericlippert.com/2014/03/05/how-to-debug-small-programs/ – slim

+0

这并不完全清楚你的代码试图做什么(尽管我们知道这是不对的)。什么是'temp'和'parent_node'指向循环的入口,你希望他们在退出循环时指向什么?两行'parent_node-> next = temp-> next;'和'temp-> next = parent_node;'似乎在创建一个包含两个节点的循环列表。那是你要的吗? –

回答

1

下面是一些代码,将插入一个新的节点指向newnode到链接列表,其中liststart指向第一个节点列表或者是NULL为空列表:

if (liststart == NULL) { 
    liststart = newnode; 
    newnode->next = NULL; 
} else { 
    struct mylist *prev = liststart; 

    while (prev->next != NULL && prev->next->frequency <= newnode->frequency) { 
     prev = prev->next; 
    } 
    if (prev->next == NULL) { 
     prev->next == newnode; 
     newnode->next = NULL; 
    } else { 
     newnode->next = prev->next->next; 
     prev->next = newnode; 
    } 
} 

下面是一个使用指针的指针的替代版本:

struct mylist **pprev; 

pprev = &liststart; 
while (*pprev != NULL && (*pprev)->frequency <= newnode->frequency) { 
    pprev = &(*pprev)->next; 
} 
newnode->next = *pprev; 
*pprev = newnode; 
3

你做temp = temp->nexttemp->next可能是nullptr。在尝试访问它的成员之前,您必须检查它是否为空。

+0

我以为我有这是因为它在'while ind == 0 && temp!= NULL'中的所有内容' –

+0

@Finlandia_C:该条件保护第3行中的取消引用,但不是在下一行中的右引号'if(temp - > frequency .. 。)'和更远。 – DarkDust

+0

'temp!= NULL'是一个,但是你也需要'temp-> next!= NULL',因为你可以访问'temp-> next'的成员。 – Sorin

0

您的问题是您检查temp不为空,然后立即更新temp,因此它可能再次为空。

(我不喜欢这个名字temp所以我把它改成node在我的例子)

如果你分解,这是最明显的,因此:

while(ind == 0 && node != null) { 
    node = node -> next; // now node might be null 
    doStuffWith(node); 
} 

相反,你可以移动分配到循环的结尾。这意味着,当然,第一次,这项任务没有发生。所以,你可能需要调用它一次外循环:

node = node -> next; // or some other initialisation of node 
while(ind == 0 && node != null) { 
    doStuffWith(node); 
    node = node -> next; 
} 

也许你已经告诉了DRY原则:“不要重复自己”,所以你可能会觉得不舒服重复node = node -> next。但是这是一个很常见的模式的一个例子,例如:

int chars = stream.read(buffer); 
while(chars != -1) { 
    doSomethingWith(buffer); 
    chars = stream.read(buffer); 
}