1

SDL2でプログラムを作成しようとしています。
コードの特定の部分で、指定されたディレクトリ パスに存在するすべてのファイルの名前を取得する関数を作成し (それらをメモリに保持する)、別の関数で、指定されたファイルが最後に存在したかどうかを確認できるようにします。ディレクトリがチェックされた瞬間。私はdirent.h自分のニーズに合わせて使用​​していますが、いくつかの問題が発生しています。

  1. すべてのファイルは (例外なく) によって適切にキャプチャされますが、使用後に常に適切にメモリにコピーされるreaddir()とは限りません(コードは以下にあります)。SDL_strdup()
  2. 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;

}

出力が異なります。クラッシュしない場合は、すべてのファイル名が正しくコピーされるか、ほとんどがコピーされ、一部には何も含まれていないか、意味不明な内容が含まれています (コメントされているように)。クラッシュした場合、使用中に Segfault が発生することもあれば、使用中に Segfault が発生することもありSDL_strdup()ます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 に答える