链表C中的内存管理

问题描述 投票:0回答:1

我正在尝试实现表示文件夹树的链表数据结构。

以下结构:

typedef struct SRC_ERROR SRC_ERROR;
struct SRC_ERROR {
    int error_code;
    char *error;
};

typedef struct SRC_FILE SRC_FILE;
struct SRC_FILE {
    char *entry;
    char md5[MD5_DIGEST_LENGTH];
};

typedef struct SRC SRC; //Source file tree with md5 entry char for source verification.
struct SRC {
    SRC_ERROR error;
    char *name;
    char *full_path;
    SRC_FILE **entries;
    SRC *next_dir;
};

想法是每个目录都将存储在SRC中,SRC_FILE用作存储每个文件的文件名和md5值的数组。

下面的scan_source()填充结构。

SRC *scan_source(char *source_path) {
    SRC* source = malloc(sizeof(SRC));
    source->error.error_code = OK;
    int count = 0;
    DIR *dir;
    struct dirent *entry;

    if(!(dir = opendir(source_path))) {
        source->error.error_code = ERROR;
        source->error.error = "Unable to open source directory.\n";
        return source;
    }

    source->entries = (SRC_FILE **) malloc(sizeof(SRC_FILE*) * count);

    if(source->entries == NULL) {
        source->error.error_code = ERROR;
        source->error.error = "Unable to allocate memory to file entry tree\n";
    }

    while((entry = readdir(dir)) != NULL ) {
        if(entry->d_type == DT_DIR) {

            char path[PATH_MAX];

            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;

            snprintf(path, sizeof(path), "%s/%s", source_path, entry->d_name);
            printf("[%s] - %s\n", entry->d_name, path);

            //add new node
            source = add_dir(source, insert_dir_node(entry->d_name, path));

            scan_source(path);
        }
        else if (entry->d_type == DT_REG) {
            printf("[FILE] - %s\n", entry->d_name);
            source->entries[count]->entry = entry->d_name; //SEGFAULT HERE
            count++;
            source->entries = realloc(source->entries, sizeof(SRC_FILE*)*(count));
        }
    }
    closedir(dir);
    return source;
}

我在内存管理方面遇到问题。当目录以某些方式构造时,我会遇到间歇性的段错误。

我已标记调试器已标记的行

 source->entries[count]->entry = entry->d_name; //SEGFAULT HERE 

我以为我为每种结构分配了内存,但是也许我没有正确地做到这一点,或者数据结构完全存在潜在的问题?

例如:

test> tree
.
└── Text

0 directories, 1 file

这会导致段故障。而这不是:

/test> tree
.
├── another sample
│   └── Text
└── sample folder

2 directories, 1 file

使用的附加功能:

SRC *add_dir(SRC *file_tree, SRC *new_dir) {
    new_dir->next_dir = file_tree;
    return new_dir;
}

SRC *insert_dir_node(char *name, char *full_path) {
    SRC *next_dir;
    next_dir = (SRC *) emalloc(sizeof(SRC));
    next_dir->name = name;
    next_dir->full_path = full_path;
    next_dir->next_dir = NULL;
    return next_dir;
}
c memory-management linked-list malloc
1个回答
0
投票

[我开始看代码,看到的第一个问题是您存储的是readdir()调用返回的指针-您应该复制其中包含的数据。

更改

source = add_dir(source, insert_dir_node(entry->d_name, path));

to

source = add_dir(source, insert_dir_node(strdup(entry->d_name), path));

看到分段错误的原因是,您总是在source->entries数组的结尾之后写。

您最初创建一个大小为0的数组:

    int count = 0;
/* ... */
    source->entries = (SRC_FILE **) malloc(sizeof(SRC_FILE*) * count);

然后设置其第一个(索引为0)元素:

            source->entries[count]->entry = entry->d_name; //SEGFAULT HERE
            count++;
            source->entries = realloc(source->entries, sizeof(SRC_FILE*)*(count));

然后将数组扩展为1个元素,然后写入第二个索引,依此类推。

您可以固定逻辑(总是为count+1元素分配空间,因为您不仅要为现有元素分配空间,而且还希望为下一个元素分配空间),或者在这种情况下可能更有效,切换到这里的链接列表结构。

© www.soinside.com 2019 - 2024. All rights reserved.