2015-12-07 203 views
0

我已經將分段錯誤縮小到引起錯誤的特定代碼行。這是一個直觀的例子,顯示我遇到的問題。嘗試獲取文件名長度時出現分段錯誤

int main() 
{ 
    char** files; 
    int sum; 
    int i; 

    DIR *d; 
    struct dirent *dir; 
    d = opendir("."); 
    if (d) 
    { 
      sum = file_sum(); 
      char* files[sum]; 
      i = 0; 

      while ((dir = readdir(d)) != NULL) 
      { 
        files[i] = dir->d_name; 
        i++; 
      } 

      closedir(d); 
    } 
    else 
    { 
      return -1; 
    } 

    int len = strlen(files[0]); /*segmentation fault here*/ 

    return 0; 
} 

本質上,程序正在做的是從當前目錄中獲取所有文件的名稱並將它們放入數組中。然後我將嘗試獲取所有文件名的大小,但是我一直在收到分段錯誤。我的理論是,文件名可能不是以null結尾的?如果這是真的,我不確定這是一個解決方法,但任何幫助表示讚賞。

謝謝

編輯:對不起,我在這裏有一個錯誤。只有當我嘗試存儲strlen返回值時纔會出現分段錯誤,因爲我現在已將代碼更改爲

+0

是什麼file_sum辦?它沒有在你的例子中定義。您也正在使用文件而無需初始化它。 –

回答

4

if塊的內部,您正在定義一個名爲files的變量。這會在函數的頂部掩蓋相同名稱的變量。這是而不是指定在更高範圍的陣列的大小,這似乎是你的意圖。因此,當您退出if塊時,內部files超出範圍,並且外部files保持未初始化狀態。然後解引用未初始化的指針,導致核心轉儲。

你想要做的就是在if塊內動態分配需要的內存來存儲你需要的內存。

另外,檢索到dir->d_name的目錄名可能會在每次調用readdir時被覆蓋,因此您還需要爲其分配空間。

編輯:

您也不需要單獨的函數來獲取文件數量。您可以使用默認大小分配陣列,並根據需要realloc擴大:

int main() 
{ 
    char** files; 
    int sum; 
    int i; 

    DIR *d; 
    struct dirent *dir; 
    d = opendir("."); 
    if (d) 
    { 
      int size = 10; 
      sum = 0; 
      files = malloc(size * sizeof(char *)); // allocate the array 
      if (files == NULL) { 
       perror("malloc failed"); 
       exit(1); 
      } 

      while ((dir = readdir(d)) != NULL) 
      { 
        if (sum >= size) { 
         // if the array is full, realloc twice the size 
         char **tmp; 
         size *= 2; 
         tmp = realloc(size * sizeof(char *)); 
         if (tmp == NULL) { 
          perror("realloc failed"); 
          exit(1); 
         } 
         files = tmp; 
        } 
        files[sum] = strdup(dir->d_name); // allocate and copy each string 
        sum++; 
      } 

      closedir(d); 
    } 
    else 
    { 
      return -1; 
    } 

    strlen(files[0]); 

    // free the individual strings 
    for (i=0; i<sum; i++) { 
     free(files[i]); 
    } 
    // free the array 
    free(files); 

    return 0; 
} 
0

使用「字符*文件[和]」是唯一安全的在2 conditons:

  • 你不是要在聲明範圍結束後訪問數組:在聲明的「if」結束後,您不會嘗試訪問「files」數組。

  • char *目標需要安全保留。這是reasonnable假設目標是後DIR-> d_name有效的權利,但在已經關閉的d DIR這是很危險的

這裏有一個簡單的修復,如果你知道有多少文件可以有你的目錄:複製dirList的dirent結構是最簡單的,但它是一個相當大的結構。您也可以使用「dirListPtr」僅複製指向dirent的指針,但您需要確保您的dirent結構仍然有效。這就是爲什麼我把「closedir」放得更遠一些。

如果你不確定文件的數量,動態分配是最好的選擇(參見dbush答案)。如果您想在其他功能中使用數據,則也需要進行分配。

#include <stdio.h> 
#include <sys/types.h> 
#include <dirent.h> 
#include <string.h> 

int main() 
{ 
    int sum; 
    int i; 

    DIR *d; 
    struct dirent* dir; 
    // you must be sure to have less than 255 files 
    struct dirent dirList[255]; 
    struct dirent* dirListPtr[255]; 
    d = opendir("."); 
    if (d) 
    { 

      i = 0; 

      while ((dir = readdir(d)) != NULL) 
      { 
        // copy the dirent information to our local variable which will live until the end of the main 
        dirList[i] = *dir; 
        // or keep only a pointer to the dirent struct: the system will surely not discard the dirent at least as long as d is open 
        dirListPtr[i] = dir; 
        i++; 
      } 

    } 
    else 
    { 
      return -1; 
    } 

    printf("size of filename: %lu size of dirent %lu\n", strlen(dirList[0].d_name), sizeof(dirList[0])); 
    printf("size of filename: %lu\n", strlen(dirListPtr[0]->d_name)); 

closedir(d); 

    return 0; 
} 

大小文件名:2大小的dirent的280

大小文件名:2

相關問題