【问题标题】:Segmentation fault on c implementation of linked list when adding nodes添加节点时链表的c实现分段错误
【发布时间】:2012-04-23 22:10:16
【问题描述】:

这段代码有段错误:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>

typedef struct _node
{
    char *buffer;           
    struct _node *next;     
    int node_count;        
} node;

typedef struct _list
{
    node *head;
    node *tail;
} list;

list *node_list;

int list_node_lookup(list *l, char *buffer)
{
    node *temp = l->head;
    while(temp)
    {
        if (strcmp(temp->buffer, buffer) == 0)
        {
            /* We got it earlier */
            temp->node_count++;

            return 1;
        }
        else
        {
            temp = temp->next;
        }

    }

    return 0;
}

int adding_to_list(list *l, char *buffer)
{
    int ret;
    char *tmp = (char *)malloc(sizeof(char)*(strlen(buffer) + 1));
    node *new_node = (node *)malloc(sizeof(struct _node));

    /* Empty list */
    if (l->head == NULL)
    {
        strcpy(tmp, buffer);
        new_node->buffer = tmp;
        new_node->node_count = 0;
        l->head = l->tail = new_node;
        l->head->next = NULL;
    }
    else
    {
        /* The list is not empty */
        ret = list_node_lookup(l, buffer);
        if (ret == 1)
        {
            fprintf(stdout, "Got it before\n");
        }
        else
        {
            strcpy(tmp, buffer);
            new_node->buffer = tmp;
            new_node->node_count = 0;
            l->tail->next = new_node;
            l->tail = new_node;
            new_node->next = NULL;
            fprintf(stdout, "Adding this cust : %s\n", buffer);
        }
    }

    return 0;
}

int main(int argc, char **argv)
{
    FILE    *cust;
    char    buf[BUFSIZ];
    DIR* cust_dir;
    struct dirent* input;

    node_list = (list *) malloc(sizeof(struct _list));
    if (node_list == NULL)
    {
            return 1;
    }
    node_list->head = node_list->tail = NULL;

    if (NULL == (cust_dir = opendir("cust_dir"))) 
    {
        return 1;
    }
    while ((input = readdir(cust_dir))) 
    {
            if (!strcmp (input->d_name, "."))
                continue;
            if (!strcmp (input->d_name, ".."))  
                continue;

            cust = fopen(input->d_name, "r");

            while (fgets(buf, BUFSIZ, cust) != NULL)
            {
                adding_to_list(node_list, buf);
            }
                    fclose(cust);
    }

    return 0;
}

当我使用包含这两个文件(它们包含空行)的目录测试我的代码时,我得到了奇怪的输出和段错误。

我在同一个目录中使用了这个文件两次(customers.txt 和 customers_copy.txt):

1
2
3
4    Kristina   Chung   H   Kristina H. Chung   Chung, Kristina H.
5    Paige  Chen    H   Paige H. Chen   Chen, Paige H.
6    Sherri Melton  E   Sherri E. Melton    Melton, Sherri E.
7    Gretchen   Hill    I   Gretchen I. Hill    Hill, Gretchen I.
8    Karen  Puckett U   Karen U. Puckett    Puckett, Karen U.
9    Patrick    Song    O   Patrick O. Song Song, Patrick O.
10    Elsie Hamilton    A   Elsie A. Hamilton   Hamilton, Elsie A.
11   
12    Hazel Bender  E   Hazel E. Bender Bender, Hazel E.
13

前三行是空的(当我使用一个文件时一切正常,但是这多个文件我得到了一个段错误)。

感谢您的帮助,了解问题所在。

【问题讨论】:

  • 在你读完第一个文件后,你永远不会关闭 fp cust,在你进入下一个文件之前,这可能会导致一些问题
  • @GregBrown :谢谢,我关闭它但没有改变任何东西。
  • 遇到分段错误时应该做的第一件事是在调试器中运行程序。这将帮助您查明错误的位置,还可以让您检查变量以帮助您找出问题的原因。
  • @JoachimPileborg :调试器在 fgets(_IO_fgets) 行显示错误。

标签: c file-io linked-list segmentation-fault


【解决方案1】:

当您将一个节点添加到列表(到列表的尾部)时,您不会将该节点的 next 指针设置为 NULL。这意味着下次您进行查找时,您将使用无效指针调用strcmp。这本身就可能导致分段错误。

简单的解决方案是在分配节点后立即将next 设置为NULL。

另外,如果节点已经在列表中,你分配tmp 但永远不要使用它。那会泄漏内存。这与 Greg Brown 的评论类似 - 您还泄漏了文件描述符和文件句柄(您永远不会关闭 cust)。

[编辑]

问题是您正在读取目录“cust_dir”,因此您正在获取目录中文件的名称(例如“customers.txt”)。然后打开文件而不在文件名中添加“cust_dir/”。

因此,如果您不小心在当前目录中也有该文件,它可以工作。但除此之外,cust 为 NULL(因为input-&gt;d_name 是“cust_dir”中的文件名,而不是当前目录中的文件名),然后您尝试从 NULL 文件指针读取数据。这会导致分段错误。

【讨论】:

  • 谢谢,但添加 new_node->next = NULL 后没有任何变化;
  • @iPadDevloperJr 你用input 打电话给fclose,但你应该用cust 打电话。这也会导致分段错误。
  • @iPadDevloperJr 你能给我们一个关于输入的想法吗?你能找到一个小的输入,你可以在这里粘贴,但仍然会导致问题?
  • 我在原始帖子我的输入目录中发布了一个输入:包含两个文件:customers.txt 和customers_copy.txt,其中包含与发布的相同数据
  • 对不起,这不是真的,我添加了目录的完整路径,但仍然改变:“分段错误:11”
猜你喜欢
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 2020-09-30
  • 2015-05-28
相关资源
最近更新 更多