使用SDL_strdup和类似方法获取文件名时出现问题

时间:2015-02-08 17:52:59

标签: c malloc sdl-2 opendir strdup

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

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

    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.

1 个答案:

答案 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,因为你无法控制你想要读取的数据的大小,并且至少在理论上你可能会耗尽内存,所以你应该制作通过检查这些函数是否成功,您的代码是安全的。