我试图用SDL2创建一个程序
在代码的某个部分,我编写函数来获取给定目录路径中所有当前文件的名称(并将它们保存在内存中),以便在另一个函数中,我可以检查指定的文件是否存在检查目录的最后一刻。
我使用dirent.h
来满足我的需求,但我遇到了一些问题:
readdir()
正确捕获(没有例外),但在使用SDL_strdup()
后,它们总是 正确地复制到内存中(代码如下) )。SDL_malloc()
/ SDL_realloc()
/ SDL_strdup()
作为跨平台,以避免在移植代码时出现问题(因为我已经阅读过strdup不是C标准)。这是我的代码:
typedef struct FileList {
char **files;
size_t num;
} FileList;
FileList *GetFileList(const char *path){
struct dirent *dp = NULL;
DIR *dir = NULL;
size_t i = 0;
FileList *filelist = SDL_malloc(sizeof(FileList)); /* changing this to a calloc doesn't help */
/* Check if filelist == NULL */
filelist->files = NULL;
dir = opendir(path);
/* Check if dir == NULL */
while ((dp = readdir(dir))){
if (dp->d_name[0] == '.'){
continue; /* skip self, parent and all files starting with . */
}
printf("Copying: %s\n", dp->d_name); /* Always show the name of each file */
filelist->files = SDL_realloc(filelist->files, ++i);
filelist->files[i-1] = SDL_strdup(dp->d_name);
printf("Copied: %s\n\n", filelist->files[i-1]); /* Varies: either shows the file's name, either gives me plain gibberish or just nothing */
}
filelist->num = i;
closedir(dir);
return filelist;
}
输出各不相同。当它没有崩溃时,我要么正确地复制了所有文件名,要么我得到大部分文件名被复制,有些不包含任何内容或者简单的乱码(如评论所示);如果它确实崩溃,有时我会在使用SDL_strdup()
时获得Segfault,有时我在使用closedir()
时会遇到Segfault。
我甚至考虑通过给它SDL_realloc()
的初始内存分配来交换filelist->files
场景,给它一些文件(感谢另一个函数),但我遇到了同样的问题。< / p>
任何建议将我的编码风格改为更具防御性的风格(因为我确实认为这个风格相当危险),我将不胜感激,尽管我已尽力为此案例做好准备。我目前正在使用内置的gcc Apple LLVM 6.0(clang-600.0.56)处理Mac OS X.
答案 0 :(得分:1)
你需要指针空间,sizeof(char *) != 1
所以
filelist->files = (char**) SDL_realloc(filelist->files, ++i);
需要
filelist->files = SDL_realloc(filelist->files, ++i * sizeof(char *));
但这实际上是一个坏主意,因为SDL_realloc
可以返回NULL
,在这种情况下你会松开对原始指针的引用,所以这样做的好方法是
void *ptr;
ptr = SDL_realloc(filelist->files, ++i * sizeof(char *));
if (ptr == NULL)
handleThisErrorAndDoNotContinue();
filelist->files = ptr;
并且总是检查分配器函数是否返回NULL
,因为你无法控制你想要读取的数据的大小,并且至少在理论上你可能会耗尽内存,所以你应该制作通过检查这些函数是否成功,您的代码是安全的。