2011-09-10 109 views
1

我想要一個返回給定目錄的內容的函數。爲此,我從dirent.h使用scandir。下面的代碼成功編譯(gcc -Wall test.c),但最後一個printf導致分段錯誤。這意味着在函數後面的「eps」結構(指向指向結構的指針數組的指針)仍然是空的:我該如何解決這個問題?在C中,當作爲參數傳遞給函數時,修改指向指向數組的指針的目標

#include <stdlib.h> 
#include <stdio.h> 
#include <dirent.h> 
#include <string.h> 

static int myselector(const struct dirent * dir_entry) 
{ 
    char * pch = strstr(dir_entry->d_name, "."); 
    return pch == NULL ? 1 : 0; 
} 

int list_dir(char * dirname, struct dirent ** eps) 
{ 
    int nbfiles = scandir(dirname, &eps, myselector, alphasort); 
    if(nbfiles > 0) 
    { 
    printf("inside function: %s\n", eps[0]->d_name); 
    return 1; 
    } 
    else 
    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    int status = 0; 
    struct dirent ** eps = NULL; 
    status = list_dir("/home", eps); 
    if (status) 
    { 
    puts("ok"); 
    printf("outside function: %s\n", eps[0]->d_name); 
    } 
    return EXIT_SUCCESS; 
} 

回答

1

因爲你的指針發生了變化,你在main()尋找錯誤的事情:)

你傳遞一個指針的指針的指針scandir()。它正在改變一個指針指向的指針(我知道,這傷害了閱讀...)。

因爲你在你的函數中調用scandir()&eps,你會在函數外面失去這種改變。您的功能中eps的值已更改。

爲了更好地理解這一點,在當前的功能包裹scandir()電話與printf()報表顯示你什麼包含在eps值:

... 
printf("%p\n", eps); 
int nbfiles = scandir(dirname, &eps, myselector, alphasort); 
printf("%p\n", eps); 
... 

爲了解決這個問題改變你的函數:

int list_dir(char * dirname, struct dirent *** eps) 
{ 
    int nbfiles = scandir(dirname, eps, myselector, alphasort); 
    if(nbfiles != -1) 
    { 
    printf("inside function: %s\n", (*eps)[0]->d_name); 
    return 1; 
    } 
    else 
    return 0; 
} 

並稱之爲...

status = list_dir("/home", &eps); 

in main()。然後,它會很好地工作:

拉@蟑螂VirtualBox的:〜$ ./test
內部功能:戳破
確定
外功能:戳破

+0

謝謝,在典型的「指向指針...」的例子中有明確的答案......我需要將它刻在我的頭上! – tflutre

1

您似乎沒有覆蓋scandir返回0即空目錄的情況。 -1的返回值僅適用於錯誤。

+0

是的,我對這個簡短的例子有點快,現在已經修復了。 – tflutre

+0

這是否修復了段錯誤? –

+0

不可以。段錯誤並不是由於輸入目錄可能爲空,而是因爲「eps」結構在我的「listd_dir」函數中填充,然後在函數完成後清空。我不知道如何防止這種情況。 – tflutre

1

製作list_dir採取struct dirent ***代替struct dirent **,在scandir()調用中除掉&運算符,並將其添加到main的list_dir()調用中。 list_dir的第一線()成爲:

int list_dir(char * dirname, struct dirent *** eps) 
{ 
    int nbfiles = scandir(dirname, eps, myselector, alphasort); 

和在主的list_dir()調用變爲:

status = list_dir("/home", &eps); 

這樣list_dir()可以讓SCANDIR()修改從主eps()通過它的地址,而不是修改參數,在棧上傳遞給list_dir()。

+0

完美,謝謝! (抱歉不要選擇你的答案,Brian Roach從幾分鐘開始就更快;) – tflutre

相關問題