2009-11-17 44 views
1

我一直在試圖調試我的代碼,只要我有一天半的空閒時間,我不知道我的代碼有什麼問題。當我將close()函數添加到遞歸調用時,該程序會給我一個無效的指針。但是,當我刪除close()函數調用的程序運行正常,但它不會做什麼是應該做的,這就是:在C中調試遞歸線程調用

  • 在用戶 輸入目錄
  • 開放加起來所有的文件大小子目錄,如果有的話,並添加 子目錄

而是裏面 的所有文件,它增加了所有的文件大小輸入目錄能夠打開最後一個子目錄,將該目錄內的文件添加到總文件大小計數中。

我想用線程做到這一點。 main()函數從用戶輸入目錄創建一個主線程,並在球杆上運行opendirectory()

/* 
* Iterates through given directory 
*/ 
void *opendirectory(void *t) 
{ 
pthread_mutex_lock(&dirlock); 
DIR *dpntr; 
struct dirent *dentry; 
char new_directory[512], dir = t; 

printf("OPENING DIRECTORY ... %s\n", t); 

/* Checks if given directory can be opened */ 
if((dpntr = opendir(t)) == NULL) { 
    printf("DIRECTORY FAILED ...%s\n",t); 
    perror("ERROR -- COULD NOT OPEN DIR"); 
    pthread_exit(NULL); 
} 

printf("DIRECTORY OPENED: %s\n", t); 

/* Read each file in current directory */ 
while ((dentry = readdir(dpntr)) != NULL) { 
    /* Ignore special directories */ 
    if(strcmp(dentry -> d_name, ".") == 0 || strcmp(dentry -> d_name, "..") == 0) { 
    continue; 
    } else { 
    compilelist(t, dentry->d_name); 
    } 
} 

pthread_mutex_unlock(&dirlock); 
/* Checks if directory can be closed */ 
if(closedir(dpntr) < 0) 
    printf("ERROR CLOSING %s.\n", t); 

} 

這是確定是否應該創建新線程並且應該遞歸運行的函數。

/* 
* Determines if current file is a directory 
* Creates a new thread if true 
*/ 
void compilelist (const char* dirname, const char *filename) 
{ 
    pthread_mutex_lock(&filelock); 
    struct stat statdata; 
    char *filepathname, *dpntr; 

    /* Allocate memory for filepathname */ 
    if((filepathname = (char *) malloc(sizeof(char) * strlen(dirname))) == NULL) 
    { 
     printf("CANNOT ALLOCATE MEMORY FOR FILE PATH NAME."); 
     pthread_exit(NULL); 
    } 

    /* Concats directory name with file name */ 
    if(dirname[strlen(dirname) -1] == '/') 
    { 
     pthread_mutex_lock(&pathlock); 
     sprintf(filepathname, "%s%s", dirname, filename); 
     pthread_mutex_unlock(&pathlock); 
    }else 
    { 
     pthread_mutex_lock(&pathlock); 
     sprintf(filepathname, "%s/%s", dirname, filename); 
     pthread_mutex_unlock(&pathlock); 
    } 

    lstat(filepathname, &statdata); 

    /* Calls print_statdata() if current item is a file */ 
    if(!(S_ISDIR(statdata.st_mode))) 
    { 
     printf("FILE: %s\n", filepathname); 
     if(!stat(filepathname, &statdata)) 
     { 
      print_statdata(filename, &statdata); 
     } 
     else { 
      fprintf (stderr, "GETTING STAT FOR %s", filepathname); 
      perror("ERROR IN STATDATA WHILE GETTING STAT"); 
     } 
    } 
    /* Recursive call to opendirectory() */ 
    else { 
     pthread_mutex_lock(&dircountlock); 
     dirCount++; 
     pthread_mutex_unlock(&dircountlock); 
     dpntr = filepathname; 
     free(filepathname); 
     printf("SUB-DIRECTORY THREAD: %s\nTHREAD ID NUMBER: %d\n", dpntr, dirCount); 
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
     pthread_create(&threads[dirCount-1], &attr, opendirectory, (void *)dpntr); 
    } 

    pthread_mutex_unlock(&filelock); 

} 

這裏是main()

/* 
* Main function prompts user for a directory 
*/ 
int main(int argc, char *argv[]) 
{ 
    int i; 
    char *dPtr; 
    // pthread_attr_t attr; 

    printf("ENTER A DIRECTORY:\n\t"); 
    scanf("%s", directory); 
    dPtr = directory; 

    /* Initialize mutex and condition variable objects */ 
    pthread_mutex_init(&mutex, NULL); 
    pthread_mutex_init(&filelock, NULL); 
    pthread_mutex_init(&dirlock, NULL); 
    pthread_mutex_init(&dircountlock, NULL); 
    pthread_cond_init (&count_threshold_cv, NULL); 

    /* For portability, explicitly create threads in a joinable state */ 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    pthread_create(&threads[0], &attr, opendirectory, (void *)dPtr); 

    /* Wait for all threads to complete */ 
    for (i = 0; i < dirCount; i++) { 
     pthread_join(threads[i], NULL); 
    } 

    printf("TOTAL DIRECTORY SIZE: %d\n", dirSize); 

    /* Clean up and exit */ 
    pthread_attr_destroy(&attr); 
    pthread_mutex_destroy(&mutex); 
    pthread_mutex_destroy(&filelock); 
    pthread_mutex_destroy(&dirlock); 
    pthread_mutex_destroy(&dircountlock); 
    pthread_cond_destroy(&count_threshold_cv); 
    pthread_exit (NULL); 

} 

而且全局變量...

pthread_mutex_t mutex; 
pthread_mutex_t dirlock; 
pthread_mutex_t filelock; 
pthread_mutex_t dircountlock; 
pthread_mutex_t threadlock; 
pthread_cond_t count_threshold_cv; 
pthread_attr_t attr; 
pthread_t threads[128]; // handles up to 128 threads (i.e. 128 directories, change accordingly) 
char directory[512]; 
int dirSize = 0; 
int dirCount = 1; // user's input directory 

我覺得所謂的compilelist()功能的底部pthread_create()工作不正常。線程[]指的是默認大小爲20的全局線程數組,假設總共不會超過20個目錄。由於用戶的輸入目錄,dirCount從1開始,並在遇到新目錄時增加。

+0

whoah,很多代碼... – stefanB 2009-11-17 01:48:14

+0

如果你想得到這個幫助,你將不得不提供整個源代碼(dPtr在哪裏聲明?dir = t是錯誤的,等等......) – Gonzalo 2009-11-17 01:58:12

+0

你能將代碼發佈到main()?或者至少你在設置線程屬性/處理連接/ etc? – 2009-11-17 01:58:38

回答

1

在這裏,我找到了你的代碼的2個問題:

  1. 由於wrang-wrang文件檔案化管理,closedir(T)導致段錯誤。 「

  2. 」char filepathname [512];「 compilelist()是一個本地內存緩衝區,但是你將它傳遞給你的線程(opendirectory)並持續使用它。您應該使用複製或動態分配。

Effo UPD @ 2009nov17: 以上2點固定之後,它在我的FC9 x86_64的正常工作爲止。順便說一句:20號線程是不夠的。

+0

現在將編輯帖子爲closedir(),忘記了在上次編輯時更新它。我一定會檢查char filepathname [512]的用法,並考慮如何去做。謝謝。 – KenjiOne 2009-11-17 02:58:03

+0

好吧,所以我相信我已經正確設置了它,而不是使用動態分配,但是我仍然在不打開子目錄的線程上發生錯誤。我會稍微發佈我的新代碼。 – KenjiOne 2009-11-17 06:11:24

+0

我不應該釋放(filepathname)嗎?我想我必須這樣做才能正確地遞歸調用malloc ... – KenjiOne 2009-11-17 06:17:51

0

第一個問題:

,每當我有空閒時間,在過去的一天半

不要這樣,你的大腦是不是專爲它。分配一段時間,告訴你的同事/妻子和孩子們,如果他們在這段時間打擾你,會有槍聲和警察參與:-)

其他問題:不知道(因此社區wiki)。

+0

哈哈...這是一個繁忙的月份:) – KenjiOne 2009-11-17 01:54:22

+1

有一點要注意,@Kenji(我不認爲這是你的*特定*問題)。我無法用粗略的眼光看到任何阻止主線程在您的子線程有機會使用它之前(通過dPtr指針)更改filepathname的內容。 – paxdiablo 2009-11-17 01:58:57

+0

我認爲你可能會做些什麼,我試圖將一些全局變量切換到本地並重新編譯... – KenjiOne 2009-11-17 02:18:37

2

您的代碼:

dpntr = opendir(t) 

...

if(closedir(t) < 0) 

應該是:

if(closedir(dpntr) < 0) 
+0

OH ...謝謝...那是一個我認真忽略的簡單錯誤,應該有三重檢查! – KenjiOne 2009-11-17 02:07:46

+0

請務必將其標記爲答案,然後 – Earlz 2009-11-17 02:20:02

+0

我已更改它,但在筆記本電腦上運行該程序時仍出現分段錯誤。目前似乎無法通過ssh'ing連接到Linux系統來測試... – KenjiOne 2009-11-17 02:23:04