【问题标题】:Double linked list; newbie attempt双链表;新手尝试
【发布时间】:2011-05-05 16:09:45
【问题描述】:

我刚刚开始学习 C,并且(似乎)到目前为止,大多数东西都是点击。但是,我在追踪双链表尝试的问题时遇到了一些麻烦。当我尝试构建/运行此代码时,我不断收到seg-fault。我正在使用 Cygwin 通过 NetBeans 提供的 gcc 进行编译。

我讨厌只转储一段代码并说“帮助”,但我不知道此时还有哪些相关的细节,所以如有必要,请随时询问细节:

#include <stdio.h>
#include <stdlib.h>

struct node_t{
    struct node_t *prev;
    struct node_t *next;
};

struct list_t{
    struct node_t *head;
    struct node_t *tail;
    int length;
};

struct node_t *new_node(void);
struct list_t *new_list(void);
int append_list_node(struct list_t *list, struct node_t *node);

int main(void) {

    int i = 0, length = 0;
    struct node_t *node;
    struct list_t *list = new_list();

    for(i = 0; i < 10; i++){
        length = append_list_node(list, new_node());
        printf("%d", length);
    }

    return 0;

}

struct node_t *new_node(void){
    struct node_t *node = malloc(sizeof(struct node_t));
    return node;
}

struct list_t *new_list(void){
    struct list_t *list = malloc(sizeof(struct list_t));
    list->length = 0;
    return list;
}

int append_list_node(struct list_t *list, struct node_t *new_node){
    if(list->head == NULL){
        list->head          = new_node; // edited
        new_node->prev      = NULL;
    }else{
        list->tail->next    = new_node;
        new_node->prev      = list->tail;
    }
    return (++list->length);
}

感谢大家的超级快速回复,所有答案都是正确的。当我简要查看F5-ing 之间的代码时,我意识到我没有设置tail,因此我决定将标记为edited 的行更改如下:

list->head = list->tail = new_node;

我也将决定使用calloc(),但是,我了解到频繁使用它会导致执行时间的大量成本,因为它正在清除和分配。想法?

【问题讨论】:

  • 你能用 GDB 运行它并说出分段错误发生在哪里吗?
  • list->tail->next = new_node; list->tail 在第一次执行时未初始化
  • @Maz:显然在我在编辑中提到的那一行。 @yurib:谢谢,检查我的编辑,希望这是一个合理的解决方案。

标签: c linked-list segmentation-fault


【解决方案1】:

使用 calloc() 分配内存。 malloc() 函数不会将内存初始化为零(因此指针将设置为 NULL)。您假设指针默认为 NULL。

【讨论】:

  • 谢谢马兹;在我的C Programming: A Modern Approach 2nd Ed.一书中,它提到calloc 的执行时间可能很昂贵。有这方面的基准吗?大量的串联呼叫是否会引起注意?
  • 我不知道 calloc() 会导致性能下降。但是,如果您愿意,可以只使用 malloc() ,然后使用 memset() 函数自己将其归零。
  • my answer 有一些关于calloc 讨论性能的问题。您可能有兴趣阅读它们。
  • 好的;我只是好奇这是有道理的,将内存归零的额外步骤会增加执行时间。在大多数情况下肯定不明显,但是如果调用具有极深递归或高迭代的东西,性能损失可能不会那么微不足道。我自己也不确定,我会去调查的。
  • @TomcatExodus:在这种情况下,无论如何您都将内存设置为 0(将长度设置为 0 并将指针设置为 NULL)。一次使用分配调用比将每个成员单独设置为 0 更快。所以在这种情况下你不会失去性能
【解决方案2】:

C 不会为你做任何初始化。所以当你这样做时:

struct list_t *new_list(void){
    struct list_t *list = malloc(sizeof(struct list_t));
    list->length = 0;
    return list;
}

list-&gt;head 可以是任何东西.. 并且可能不会为 NULL。

【讨论】:

  • 谢谢克劳迪乌;我现在正在使用显式初始化更新我的代码。
【解决方案3】:

一个问题是,您永远不会将 list->tail 设置为 anything,然后如果 list->head 不为 NULL(与其他已经指出,无论如何都不能保证。)

【讨论】:

  • 谢谢dlev;我在发帖后半秒钟注意到了这一点。 哎呀! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 2015-02-25
相关资源
最近更新 更多