1

我正在尝试使用 SDL2 创建一个程序。
在代码的某个部分,我正在编写函数来获取给定目录路径中所有当前文件的名称(并将它们保存在内存中),以便在另一个函数中,我可以检查指定文件是否最后出现检查目录的那一刻。我正在使用dirent.h以满足我的需求,但我遇到了一些问题:

  1. 所有文件都被正确捕获readdir()(没有例外),但是在使用后它们并不总是正确复制到内存中SDL_strdup()(代码如下)。
  2. 我使用SDL_malloc()//尽可能跨平台以避免在移植代码时出现问题(因为我已经读过 strdup 不是 C 标准)SDL_realloc()SDL_strdup()

这是我的代码:

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;

}

输出不同。当它不崩溃时,我要么正确复制所有文件名,要么复制大部分文件名,其中一些不包含任何内容或纯乱码(如评论);如果它确实崩溃了,有时我在使用时会出现 Segfault,有时在使用SDL_strdup()时会出现 Segfault closedir()

我什至考虑过通过给它提供文件数量(感谢另一个函数)来SDL_realloc()用初始内存分配交换场景,但我遇到了同样的问题。filelist->files

任何将我的编码风格更改为更具防御性的风格的建议(因为我确实相信这种风格相当危险)将不胜感激,尽管我已经为这种情况尽我所能。我目前正在使用内置 gcc Apple LLVM 6.0 (clang-600.0.56) 开发 Mac OS X。

4

1 回答 1

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,因为您无法控制尝试读取的数据的大小,并且至少在理论上可能会耗尽内存,因此您应该通过检查成功来确保代码安全这些功能。

于 2015-02-08T18:00:49.850 回答