-1

このコードでセグメンテーション違反が発生しました:

#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;
}

この2つのファイル(空の行が含まれている)を含むディレクトリでコードをテストすると、奇妙な出力とセグメンテーション違反が発生しました。

同じディレクトリでこのファイルを2回使用します(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

最初の3行は空です(1つのファイルを使用すると、すべて問題ありませんが、この複数のファイルでセグメンテーション違反が発生します)。

何が悪いのかを理解するために、あなたの助けに感謝します。

4

1 に答える 1

1

リストに(リストの末尾に)ノードを追加する場合、nextそのノードのポインターをNULLに設定しません。つまり、次にルックアップを実行するときにstrcmp、無効なポインタを使用して呼び出すことになります。これ自体がセグメンテーション違反を引き起こす可能性があります。

簡単な解決策はnext、ノードを割り当てたらすぐにNULLに設定することです。

また、ノードがすでにリストにある場合は、割り当てますtmpが、使用することはありません。それはメモリをリークします。これは、Greg Brownによるコメントに似ています。ファイル記述子とファイルハンドルもリークしています(閉じることはありませんcust)。

[編集]

問題は、ディレクトリ "cust_dir"を読み取っているため、ディレクトリ内にあるファイルの名前( "customers.txt"など)を取得していることです。次に、ファイル名に「cust_dir/」を追加せずにファイルを開きます。

したがって、誤って現在のディレクトリにもファイルがある場合は、機能します。ただし、それ以外の場合custはNULLであり(input->d_name現在のディレクトリではなく、「cust_dir」内のファイルの名前であるため)、NULLファイルポインタからデータを読み取ろうとします。これにより、セグメンテーション違反が発生します。

于 2012-04-23T22:30:58.050 に答える