【问题标题】:Data corruption in malloc'ed memorymalloc'ed 内存中的数据损坏
【发布时间】:2019-07-21 15:48:50
【问题描述】:

当我尝试访问使用malloc 获取的内存中的数据时,数据已损坏

我正在编写一个程序,它读取 Linux 目录并将文件和子目录的名称写入“字符串数组”(c 中的 char** 数组)。它使用dirent.h 功能(如readdir())运行。 readdir 返回一个具有dname[256] 的dirent 结构,它是目标目录中文件/子目录的名称。我将 dirent string(char*) 等同于 char** 数组中 malloced 位置的索引

我基本上有一个 walk_path() 函数,它读取目录条目并将它们的名称写入分配的位置,然后返回该位置

data_t* walk_path(char* path) {
    int size = 0;

    if(path == NULL){
        printf("NULL path\n");
        return NULL;
    }
    struct dirent* entry;
    DIR* dir_l = opendir(path);

    if(dir_l == NULL) {
        char** data = (char**)malloc(sizeof(char*) * 2);
        data[0] = path;
        data_t* ret = (data_t*)malloc(sizeof(data_t));
        ret->data = data;
        ret->size = 1;
        return ret;
    }

    while((entry = readdir(dir_l)) != NULL) {
        if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
            continue;
        size++;
    }
    closedir(dir_l);

    char** data = (char**)malloc(sizeof(char*) * size + 1);
    int loop_v = 0;
    dir_l = opendir(path);

    while((entry = readdir(dir_l)) != NULL && loop_v < size) {
        if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
            continue;
        data[loop_v] = entry->d_name;
        loop_v++;
    }

    closedir(dir_l);

    data_t* ret = (data_t*)malloc(sizeof(data_t*));
    ret->size = (size_t)size;
    ret->data = data;
    return ret;
}

还有一个合并路径函数,可以获取两个目录并将它们的数据写入单个数组

char** merge_path(char* path, char* path2) {
    data_t* path_data = walk_path(path);
    data_t* path2_data = walk_path(path2);
    if(path_data == NULL || path2_data == NULL) {
        printf("Merge failed, couldn't get path data\n");
        return NULL;
    }

    char** new_dir_info = (char**)malloc(sizeof(char*) * (path2_data->size + path_data->size) );
    if(new_dir_info == NULL)
        return NULL;

    int loop = 0;
    while(loop < path_data->size) {
        new_dir_info[loop] = path_data->data[loop];
        loop++;
    }
    loop = 0;
    while(loop < path2_data->size) {
        new_dir_info[loop + path_data->size] = path2_data->data[loop];
        loop++;
    }
    free(path_data);
    free(path2_data);
    return new_dir_info;
}

合并路径函数返回的char** 数组始终具有损坏的数据,即字符数组中的字符已损坏,而不是指针本身已损坏,尽管我希望它具有从目录条目传递给它的字符串它反而有随机字符串。

我已经单步执行了代码,发现数据在合并路径函数中被破坏,错误的来源仍然可能来自walk_path()

【问题讨论】:

  • sizeof(char*) * size + 1 这是正确的吗?您想分配size 指向char 的指针计数和一个字节?
  • 是的,我打算将那个额外的字节用于不同的数据,或者只是作为数组末尾的空标识符。

标签: c arrays string directory malloc


【解决方案1】:

这个

   data_t* ret = (data_t*)malloc(sizeof(data_t*));

应该是

   data_t* ret = (data_t*)malloc(sizeof(data_t));

一般在 C 语言中 void-pointers 不需要强制转换,所以你的代码中所有对 malloc 的强制转换都可以去掉,这使得上面的行看起来像:

   data_t* ret = malloc(sizeof(data_t*));

此外,为了排除像这样的错误,最好在对 malloc() 的调用中将类型加倍为 mallocate,但最好将变量与解引用运算符一起使用,如下所示:

   data_t* ret = malloc(sizeof *ret);

还有这一行

    data[loop_v] = entry->d_name;

复制指向条目名称的指针,而不是名称本身。

考虑使用

   data[loop_v] = strdup(entry->d_name);

entry-&gt;d_name 指向的副本动态分配空间。

替代

   char**data;

定义

   char (*data)[sizeof entry->d_name]; /* Array of pointers to char[as many char as entry->d_name is defined to have] */

   char (*data)[sizeof ((struct dirent*)NULL)->d_name]; /* Array of pointers to char[as many char as entry->d_name is defined to have] */

并像这样分配给它(遵循上述建议的模式):

   data = malloc((size /* + 1 */) * sizeof *data); /* Not sure what the idea behind this +1 is. */

而不是

   data[loop_v] = strdup(entry->d_name);

   strcpy(data[loop_v], entry->d_name);

如果走这条路,你需要相应地调整data_t.data的定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多