2015-02-08 87 views
1

我試圖用SDL2創建程序。
在代碼的某個部分,我正在編寫函數來抓取給定目錄路徑中所有當前文件的名稱(並將它們保存在內存中),以便在另一個函數中,我可以檢查指定文件是否存在目錄被檢查的最後一刻。 我使用dirent.h適合我的需要,但我遇到了一些問題:使用SDL_strdup和類似方法獲取文件名的問題

  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; 

}

輸出變化。當它沒有崩潰時,我要麼正確複製所有文件名,要麼我將它們中的大多數複製,並且其中一些不包含任何內容或簡單的亂碼(如註釋);如果它確實崩潰了,有時我會在使用SDL_strdup()時遇到Segfault,其他時候使用closedir()時會出現Segfault錯誤。

我甚至考慮過交換SDL_realloc()場景,初始內存分配爲filelist->files,給它一些文件(感謝另一個函數),但是我得到了同樣的問題。

任何建議將我的編碼風格改爲更具防禦性的風格(因爲我確實相信這個風險相當危險),不勝感激,儘管我已經盡力爲這種情況盡力了。我目前正在使用內置的gcc Apple LLVM 6.0(clang-600.0.56)在Mac OS X上工作。

+0

您不需要從'void *'強制轉換爲任何指針類型,該強制轉換是不必要的。 – 2015-02-08 17:59:56

+0

我在大學裏被教過,因爲他們聲稱這是一種古老而又防守的方式。我也相信這是沒有必要的,所以我會就此提出你的建議。 – Keyaku 2015-02-08 18:02:16

+0

[這被認爲是不好的風格](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – 2015-02-08 18:10:32

回答

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,因爲您無法控制要讀取的數據的大小,並且至少在理論上可能會用完內存,所以您應該通過檢查來確保代碼安全這些功能的成功。

+0

啊,我明白了。重新分配時,指針的大小很重要。我認爲我不需要指定char(1字節),但現在我明白了。 – Keyaku 2015-02-08 18:07:17

+0

'char'總是'1'字節,但是你正在分配指針,而不是'char'。 – 2015-02-08 18:09:55

+0

是的,我明白這是我的錯誤。在這種情況下,我迷惑了兩個人,我真誠地不知道爲什麼。我爲此道歉。經過一些測試後,我可以說它是有效的,或者我可以說,自從我使用您的解決方案以來,我還沒有遇到同樣的問題。 – Keyaku 2015-02-08 18:25:32

相關問題