Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用SDL_strdup和类似工具获取文件名时出现问题_C_Malloc_Sdl 2_Opendir_Strdup - Fatal编程技术网

C 使用SDL_strdup和类似工具获取文件名时出现问题

C 使用SDL_strdup和类似工具获取文件名时出现问题,c,malloc,sdl-2,opendir,strdup,C,Malloc,Sdl 2,Opendir,Strdup,我正在尝试使用SDL2创建一个程序。 在代码的某一部分中,我正在编写函数来获取给定目录路径中所有当前文件的名称(并将它们保存在内存中),以便在另一个函数中,我可以在最后一次检查目录时检查指定文件是否存在。 我正在使用dirent.h来满足我的需要,但我遇到了一些问题: 所有文件都由readdir()正确捕获(无例外),但是在使用SDL\u strdup()后,它们并不总是正确复制到内存中(代码如下) 我正在使用SDL\u malloc()/SDL\u realloc()/SDL\u strdup

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

  • 所有文件都由
    readdir()
    正确捕获(无例外),但是在使用
    SDL\u strdup()
    后,它们并不总是正确复制到内存中(代码如下)
  • 我正在使用
    SDL\u malloc()
    /
    SDL\u realloc()
    /
    SDL\u 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\u strdup()
    时会出现Segfault,有时在使用
    closedir()
    时会出现Segfault

    我甚至考虑过用
    filelist->files
    的初始内存分配来交换
    SDL\u realloc()
    场景,方法是给它指定文件数(多亏了另一个函数),但我遇到了同样的问题


    任何将我的编码风格改为更具防御性的(因为我确实认为这是相当危险的)的建议都会得到赞赏,尽管我已经为此尽了全力。我目前正在使用内置的gcc Apple LLVM 6.0(clang-600.0.56)开发Mac OS X。

    您需要为指针留出空间,并且
    sizeof(char*)!=1
    so

    filelist->files = (char**) SDL_realloc(filelist->files, ++i);
    
    需要

    filelist->files = SDL_realloc(filelist->files, ++i * sizeof(char *));
    
    但这实际上是个坏主意,因为
    SDL\u realloc
    可能返回
    NULL
    ,在这种情况下,您将失去对原始指针的引用,因此这样做是一个好方法

    void *ptr;
    
    ptr = SDL_realloc(filelist->files, ++i * sizeof(char *));
    if (ptr == NULL)
        handleThisErrorAndDoNotContinue();
    filelist->files = ptr;
    

    如果分配器函数返回
    NULL
    ,请始终检查它们,因为您无法控制要读取的数据的大小,并且至少在理论上可能会耗尽内存,因此,您应该通过检查这些函数的成功与否来确保代码的安全。

    您不需要从
    void*
    强制转换为任何指针类型,强制转换是不必要的。我在大学里学到了这一点,因为他们声称这是一种古老但防御性的编程方式。我也认为这是没有必要的,所以我会接受你的建议。我只是仔细阅读了一下。那就再也不会了。啊,我明白了。重新分配时,指针的大小很重要。我原以为在使用char(1字节)时不需要指定,但现在我明白了。
    char
    始终是
    1
    字节,但您分配的是指针,而不是
    char
    。是的,我明白这是我的错误。我把这两个人搞糊涂了,我真的不知道为什么。我为此道歉。经过一些测试,我可以说它是有效的,或者我可以说自从我使用你的解决方案以来,我从未遇到过同样的问题。