链表只是偶尔给出 segv

Linked list gives segv only occasionally

我需要实现一个链表,将文件名和信息存储为每个节点。 我决定将节点填充为:

struct node
{
    struct stat st;
    char filename[FILENAME_MAX];
    struct node *next;
};

我希望我的程序根据任何给定目录中的文件名创建一个链接列表。 我已经做了几个函数来完成这个。

(xmalloc 只是 malloc 的包装器,如果 malloc returns null 由于某种原因退出程序) 将节点添加到现有列表:

struct node *
add_list(struct node **head, struct node n)
{
    struct node *new = xmalloc(sizeof(struct node));
    memcpy(new, &n, sizeof(struct node));
    new->next = NULL;

    new->next = *head;
    *head = new;
    return new;
}

正在用给定目录中的文件填充列表:

int
fill_list(struct node **head, const char *dirname)
{
    DIR *dir;
    struct dirent *de;

    if ((dir = opendir(dirname)) == NULL)
    {
        perror("(fill_list) opendir");
        free_list(head);
        exit(EXIT_FAILURE);
    }
    while (de = readdir(dir))
    {
        // Don't add entries for parent dir and current fir
        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
            continue;

        struct node new_node;
        new_node.next = NULL;
        strncpy((new_node.filename), (de->d_name), FILENAME_MAX);
        stat(de->d_name, &(new_node.st));

        add_list(head, new_node);
    }
}

释放现有列表:

free_list(struct node** head)
{
 
    struct node* current = *head;
    struct node* next = NULL;
 
    while (current->next != NULL)
    {
        next = current->next;
        printf("free: %p\n", current);
        current = next;
    }
 
    *head = NULL;
}

最后,打印列表的内容:

int
print_list(struct node *head)
{
    while (head->next)
    {
        printf("%s: %ld\n", head->filename, head->st.st_size);
        head = head->next;
    }
}

我的主要功能是

int main(void)
{
    struct node *head;
    fill_list(&head, ".");

    print_list(head);
    free_list(&head);
}

出于某种原因,当我 运行 这段代码时,我有时会遇到分段错误,但并非总是如此。 我的目录包含 a.out list.h llist.c log_synfiles.log syncfiles syncfiles.c test.c 当 运行 正常时,就会出现内存泄漏。 为什么会这样?

For some reason, when I run this code, I get a segmentation fault sometimes, not always.

使用 Memory Sanitizer 构建您的程序,运行 它产生:

==11652==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x49a500 in print_list /tmp/t.c:74:5
    #1 0x49a704 in main /tmp/t.c:86:5
    #2 0x7f8815606e49 in __libc_start_main csu/../csu/libc-start.c:314:16
    #3 0x41f269 in _start (/tmp/a.out+0x41f269)

第 74 行是:

    72  print_list(struct node *head)
    73  {
    74      while (head->next)
    75      {
    76          printf("%s: %ld\n", head->filename, head->st.st_size);
    77          head = head->next;
    78      }
    79  }

发生这种情况是因为您“链接”到 main 中定义的 head,但 head 本身从未初始化。修复:

    81  int main(void)
    82  {
    83      struct node *head = NULL;  // <<<--- initialize it.
    84      fill_list(&head, ".");

And the times when it runs properly, there's a memory leak.

当然有:

    34      while (current->next != NULL)
    35      {
    36          next = current->next;
    37          printf("free: %p\n", current);
--->>>          free(current);   // Did you intend to free memory here?
    38          current = next;
    39      }
--->>>      free(current);  // Also need to free the last node.
    40
    41      *head = NULL;
    42  }

您还必须调用 closedir() 来释放 opendir() 分配的 DIR