2012-03-11 75 views
0

我創建了一個函數,它創建一個動態字符串長度的動態字符串數組,然後將其返回到我的主函數。一切工作正常我的函數內,但是當我嘗試在主要打印數組時,我得到第四個字符串後的分段錯誤 - 前兩個字符串不打印出正確的。程序的這部分應該找出目錄及其子目錄中的所有條目並將它們存儲在主內存中。段錯誤從函數返回字符串數組

這裏的結果:

Path[0]=A/New Folder. - i=0 
Path[1]=A/atext - i=1 
Path[2]=A/a - i=2 
Path[3]=A/alink - i=3 
Path[4]=A/afolder - i=4 
Path[5]=A/afolder/set008.pdf - i=0 
Path[6]=A/afolder/anotherfolder - i=1 
Path[7]=A/afolder/anotherfolder/folderOfAnotherFolder - i=0 
Path[8]=A/afolder/anotherfolder/folderOfAnotherFolder/mytext - i=0 
Path[9]=A/afolder/anotherfolder/mytext - i=1 
Path[10]=A/afolder/set001.pdf - i=2 
Entries in directory: A 
�� 
�� 
A/a 
A/alink 
Segmentation fault 

而這裏的代碼: 功能:

char ** getDirContents(char *dirName,char **paths) 
{ 
    DIR * tmpDir; 
    struct dirent * entry; 
    //char tmpName[512]; 
    char * tmpName=NULL; 
    struct stat node; 
    int size=0; 
    int i=0; 
    //paths=NULL; 

    if((tmpDir=opendir(dirName))==NULL){ 
     perror("getDirContents opendir"); 
     return NULL; 
    } 
    i=0; 
    while ((entry=readdir(tmpDir))!=NULL) 
    { 
     //if (entry->d_ino==0) continue; 
     if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)//Ignore root & parent directories 
      continue;but I 

     tmpName =(char *)malloc(strlen(dirName)+strlen(entry->d_name)+2); 
     strcpy(tmpName,dirName); 
     strcat(tmpName,"/"); 
     strcat(tmpName,entry->d_name); 
     //printf("\ntmpName[%d]:%s",count,tmpName); 

     paths=(char**)realloc(paths,sizeof(char*)*(count+1)); 
     paths[count]=NULL; 
     //paths[count]=(char*)realloc(paths[count],strlen(tmpName)+1); 
     paths[count]=(char*)malloc(strlen(tmpName)+1); 

     //memcpy(paths[count],tmpName,strlen(tmpName)+1); 
     strcpy(paths[count],tmpName); 
     printf("\nPath[%d]=%s - i=%d",count,paths[count],i); 

     count++; 

     if(lstat(tmpName,&node)<0)  
      { 
       printf("\ntmpName:%s",tmpName); 
       perror("getDirContents Stat"); 
       exit(0); 
      } 
     if (S_ISDIR(node.st_mode)) 
      { 
       getDirContents(tmpName,paths);//Subfolder 
      } 

     //printf("\n%s,iters:%d",tmpName,i); 
     free(tmpName); 
     tmpName=NULL; 
     i++; 
    } 
close(tmpDir); 
return(paths); 
} 

主:

char **A=NULL; 
count=0; 
A=getDirContents(dir1,NULL); 
Aentries=count; 
count=0; 
//B=getDirContents(dir2,NULL); 
printf("\nEntries in directory: %s",dir1); 
for(i=0;i<Aentries;i++) 
{ 
    printf("\n%s",A[i]); 
} 

計數是一個全局變量

我只是無法弄清楚什麼是錯誤的,我想我正確地使用了返回命令。我也嘗試了與路徑相同的代碼作爲全局變量,並且它工作正常(主要打印出正確的結果)。 我有一種感覺它是與我的函數的遞歸調用

+3

請把它歸結爲一個簡單的測試用例(不超過10-15行)。請參閱http://sscce.org。 – 2012-03-11 16:16:32

+1

嗯,找到它。這真的是我的功能 recudive電話我改變了這個:getDirContents(tmpName,paths); //子文件夾: paths = getDirContents(tmpName,paths); //子文件夾 它現在正常工作 – 2012-03-11 16:18:58

+0

什麼是count ',全球? – phoxis 2012-03-11 16:19:36

回答

1

你的代碼中有一個未定義行爲

你調用該函數爲:

A=getDirContents(dir1,NULL); 

和函數定義爲:

char ** getDirContents(char *dirName,char **paths) 

而且你打電話pathsrealloc

paths=(char**)realloc(paths,sizeof(char*)*(count+1)); 

這會導致未定義的行爲。

標準要求傳遞給realloc的指針應該與使用內存管理函數分配動態內存的指針完全匹配。該標準規定的存儲器管理功能是: aligned_alloc,calloc,mallocrealloc

您傳遞給realloc()的指針(paths)未被任何這些返回,因此未定義的行爲。

+0

我不明白爲什麼它是不確定的,我改變了這個 getDirContents(tmpName,路徑); //子文件夾 爲路徑= getDirContents(tmpName,路徑); //子文件夾 它仍然是不確定的行爲?來自主要問題的調用中的NULL參數?調用路徑上的realloc有什麼問題? – 2012-03-11 21:59:35

+0

哦,我想我明白了你的意思 – 2012-03-11 22:04:51

+2

等等,什麼?用'NULL'指針調用'realloc'是明確定義的行爲:C11,7.22.3.5/3,*「如果'ptr'是一個空指針,'realloc'函數的行爲與 的'malloc'函數指定的大小。「* – netcoder 2013-01-14 20:40:58

1

您的問題是,按照標準,你realloc通話可能(可能會)返回一個指向不同的內存位置比原來的

這是一個棘手的問題,這有點難以解釋和可視化,但我會盡我所能。

當你最初調用你的函數時,它會創建一個新的棧幀(我們稱之爲A)。它將paths分配給一個地址(比如0x01),用它做一些事情,然後該函數以paths地址作爲參數遞歸地調用它自己。

當你打電話給你的函數遞歸,它會創建一個新的堆棧幀(姑且稱之爲B),在其中reallocpaths指針 - 這改變從0x010x02其地址 - 做一些東西吧,然後返回它。

但當B返回時,paths指針A仍然指向舊的位置,0x01,即使它不再有效,並已被轉移到0x02

解決方案很簡單,確保當遞歸調用結束時您指向paths到新位置。因此,而不是:

getDirContents(tmpName,paths); //Subfolder 

...你會怎麼做:

paths = getDirContents(tmpName,paths); //Subfolder 

此外,請務必檢查的reallocmalloc(對NULL)的返回值,並don't cast the return value of malloc