每当我尝试访问使用所获取的内存中malloc
的数据时,数据就会损坏
我正在编写一个程序,该程序读取Linux目录并将文件和子目录的名称写在“字符串数组”(c中的char **数组)中。它使用dirent.h
诸如之类的功能进行操作readdir()
。readdir返回一个Dirent结构,该结构的a dname[256]
就是目标目录中文件/子目录的名称。我将Dirent字符串(char *)等同于char **数组中已分配位置的索引
我基本上有一个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_vd_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(loopsize) { new_dir_info[loop] = path_data->data[loop]; loop++; } loop = 0; while(loop 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()
。
这个
data_t* ret = (data_t*)malloc(sizeof(data_t*));
必定是
data_t* ret = (data_t*)malloc(sizeof(data_t));
通常,在C void
指针中不需要强制转换,因此malloc
可以删除代码中的所有强制转换,这使上面的行看起来像:
data_t* ret = malloc(sizeof(data_t*));
排除此类错误的更多方法是,最好不要再将类型加倍以在to malloc
的调用中使用malloc()
,而是更好地使用变量与取消引用运算符一起分配给,例如:
data_t* ret = malloc(sizeof *ret);
也是这条线
data[loop_v] = entry->d_name;
复制指向条目名称的指针,而不是名称本身。
考虑使用
data[loop_v] = strdup(entry->d_name);
它动态地为entry->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
。