简体   繁体   English

分配内存中的数据损坏

[英]Data corruption in malloc'ed memory

When ever I try to access data in memory that I've acquired using malloc , the data is corrupted 每当我尝试访问使用malloc获取的malloc中的数据时,数据就会损坏

I'm writing a program that reads Linux directories and writes the names of the files and sub-directories in a "string array" (char** array in c). 我正在编写一个程序,该程序读取Linux目录并在“字符串数组”(c中的char **数组)中写入文件和子目录的名称。 It operates using dirent.h functionalities like readdir() . 它使用dirent.h功能(如readdir() readdir returns a dirent structure that has a dname[256] that's the name of a file/sub-directory in the target directory. readdir返回一个Dirent结构,该结构具有dname[256] ,即目标目录中文件/子目录的名称。 I equate the dirent string(char*) to an index of a malloced position in a char** array 我将Dirent字符串(char *)等同于char **数组中已分配位置的索引

I basically have a walk_path() function that reads the directory entries and writes their names into a malloced location then return that location 我基本上有一个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;
}

and a merge path function that can take two directories and write their data into a single array 以及合并路径功能,该功能可以获取两个目录并将其数据写入单个数组

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

The char** array that the merge path function returns always has corrupted data, that is the characters in the character arrays are corrupted and not the pointers themselves, though I expect it to have the strings passed to it from the directory entries it instead has random strings. 合并路径函数返回的char**数组始终具有损坏的数据,即字符数组中的字符已损坏,而不是指针本身,尽管我希望它具有从它具有的目录条目传递给它的字符串随机字符串。

I've stepped through the code and found that the data gets corrupted in merge path function, the source of the error could still originate from walk_path() . 我单步执行代码,发现合并路径功能中的数据已损坏,错误源仍可能源自walk_path()

This 这个

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

ought to be 必定是

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

Generally in C void -pointers do not need to be casted, so all casts to malloc in your code can be dropped, which made the above line look like: 通常,在C中,不需要对void指针进行强制转换,因此可以删除代码中对malloc所有强制转换,这使上面的行类似于:

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

More over to rule out bugs like this one better step away from doubling the type to malloc ate inside the call to malloc() , but better use the variable to allocate to along with the dereferencing operator, like this: 更多在排除盲蝽象这一个更好的阶梯从类型加倍到远malloc吃调用内部malloc()但最好使用可变分配与对其操作,这样一起:

   data_t* ret = malloc(sizeof *ret);

Also this line 也是这条线

    data[loop_v] = entry->d_name;

copies a pointer to the entry name, not the name itself. 复制指向条目名称的指针,而不是名称本身。

Consider using 考虑使用

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

which dynamically allocates room for a copy of where entry->d_name points to. 它动态地为entry->d_name指向的副本分配空间。

Alternatively instead of 替代代替

   char**data;

define 限定

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

or 要么

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

and allocate to it like this (following the above proposed pattern): 并像这样分配给它(遵循上述建议的模式):

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

And instead of 而不是

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

do

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

If going this route you need to adjust the definition of data_t.data accordingly. 如果采用这种方法,则需要相应地调整data_t.data的定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM