2010-07-04 60 views
1

我有以下代碼。它給了我一個空閒內存的問題,但我還沒有弄清楚問題到底是什麼。看來getpwuid(buf->st_uid);readdir(dirh);或stat功能不相符。有誰知道爲什麼?問題與getpwuid()和stat()

buf = (struct stat*) malloc(sizeof(struct stat));   
for (dirp[i] = readdir(dirh); dirp[i] != NULL; dirp[++i] = readdir(dirh)){ 

    ptr=(char *)malloc(sizeof(strlen(mydir))); 

    ptr=strdup(mydir); 
    strcat(ptr,dirp[i]->d_name); 

    stat(ptr,buf); 
    //modos(); 

    getpwuid(buf->st_uid); 
    printf("\t%s\n",ptr); 

    //we free the buf memory 
} 

free(buf); 
closedir(dirh); 

回答

3

您不爲字符串分配足夠的空間。

你做了一個非正統的長度計算,忽略了'mydir'的實際長度;您然後製作一個目錄名稱的好副本(但會泄漏以前分配的內存);然後在strdup()分配的空間末尾連接名稱,這總是很糟糕。如果省略sizeof(),那麼對於以空結尾的目錄字符串,您將分配一個字節太少。

你也不應該緩存從readdir()單獨的返回值,因爲它通常每次返回一個指向同一位內存的指針。當然,您無權假定其他情況。

如果你真的在循環中釋放buf,你也在踐踏釋放的內存;你只分配一次,並多次釋放。

通常情況下,你根本就不會費心去分配buf;它不是那麼大的一個結構。

你也不明顯地在目錄名和文件名組件之間有一個斜槓分隔符;如果你確保mydir有一個結尾,這可能無關緊要。


這是一個簡單的程序,或多或少地做什麼是必要的。

#include <stdio.h> 
#include <dirent.h> 
#include <sys/stat.h> 
#include <pwd.h> 
#include <string.h> 
#include <stdlib.h> 

int main(void) 
{ 
    static const char mydir[] = "./"; 
    DIR *dirh; 
    size_t dlen = strlen(mydir) + 1; 

    if ((dirh = opendir(mydir)) != 0) 
    { 
     struct dirent *dirp; 
     while ((dirp = readdir(dirh)) != 0) 
     { 
      char *str = malloc(dlen + strlen(dirp->d_name)); 
      if (str != 0) 
      { 
       struct stat buf; 
       strcpy(str, mydir); 
       strcat(str, dirp->d_name); 
       if (stat(str, &buf) == 0) 
       { 
        struct passwd *pwd = getpwuid(buf.st_uid); 
        if (pwd != 0) 
         printf("\t%s (%s)\n", str, pwd->pw_name); 
       } 
       free(str); 
      } 
     } 
     closedir(dirh); 
    } 
    return 0; 
} 

注:dlen的計算是正確的,但只是因爲mydir值包括最後的斜線。如果目錄名稱不包含尾部斜線,則代碼需要更改長度計算並格式化複合名稱(strcpy()strcat()序列)。謹防!

4
ptr=(char *)malloc(sizeof(strlen(mydir))); 
ptr=strdup(mydir); 

看起來有問題的最好:-)

你分配在第一一些內存泄漏,然後當你在第二個分配更多的內存。

即使這不是一個問題,我從來沒有見過的範例:

sizeof(strlen(mydir)) 

你往往會調用malloc時要麼使用sizeofstrlen()+1。我認爲你有什麼,即使它有效,也會爲size_t分配足夠的空間,從strlen返回值。我可能在這方面有錯,但我認爲這並不重要,因爲由於泄漏而無法使用該記憶。

還有其他的問題,比如:

  • getpwuid應該返回一個struct passwd *您選擇忽略。
  • strdup給你一個字符串的副本正好正確的大小,然後你strcat對它,幾乎肯定會損壞內存。

現在,這是未經測試,但我認爲它可能是一個更好的起點位置:

struct stat buf; 
struct dirent * direntp; 
struct passwd * pwdp 
for (direntp = readdir(dirh); direntp != NULL; direntp = readdir(dirh)) { 
    // Allocate enough space for directory, separator, file and nul character. 

    ptr = (char*)malloc (strlen(mydir) + 1 + strlen (direntp->d_name) + 1); 

    strcpy (ptr, mydir); 
    strcat (ptr,"/"); 
    strcat (ptr, direntp->d_name); 

    stat(ptr, &buf); 
    //modos(); 

    pwdp = getpwuid (buf.st_uid); 
    printf("\t%s\n",ptr); // prob. need something from pwdp printed here as well. 

    // Don't leak.  
    free (ptr); 
} 

closedir(dirh); 
+0

如果您的操作系統提供了'fstatat()',那麼你就需要構建路徑 - 你可以做'fstatat(dirfd(dirh),direntp-> d_name,&buf,0)' – caf 2010-07-04 07:01:03