2016-11-23 10 views
-1

割り当てのために、cでls -l機能を実装する必要があります。後でデータを操作できるように、すべての情報を文字列配列に変換しようとしています。それはwhileループ内でうまく印刷しますが、内容配列を印刷しようとすると壊れます。このエラーの原因は何ですか?c:ls -l implementationは未定義の動作を与えます

int getContentsLong(const char *dir, char **contents) 
{ 
    DIR *dp = NULL; 
    struct dirent *dptr = NULL; 
    struct stat fileStat; 

    if (dir == NULL) 
    { 
     printf("ERROR\n"); 
     return -1; 
    } 
    dp = opendir(dir); 
    if (dp == NULL) 
    { 
     printf("ERROR\n"); 
     return -1; 
    } 
    int cnt = 0; 
    char toRtn[512]; 
    char path[256]; 
    while ((dptr = readdir(dp)) != NULL) 
    { 
     strcpy(path, dir); 
     strcat(path, "/"); 
     strcat(path, dptr->d_name); 
     stat(path, &fileStat); 
     strcpy(path, " "); 

     //getting l info 
     //permissions 
     toRtn[0] = ((S_ISDIR(fileStat.st_mode)) ? 'd' : '-'); 
     strcat(toRtn, (fileStat.st_mode & S_IRUSR) ? "r" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IWUSR) ? "w" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IXUSR) ? "x" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IRGRP) ? "r" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IWGRP) ? "w" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IXGRP) ? "x" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IROTH) ? "r" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IWOTH) ? "w" : "-"); 
     strcat(toRtn, (fileStat.st_mode & S_IXOTH) ? "x" : "-"); 
     strcat(toRtn, " "); 

     //links 
     char tmp[sizeof(long int)]; 
     sprintf(tmp, "%d", fileStat.st_nlink); 
     strcat(toRtn, tmp); 
     strcat(toRtn, " "); 

     //owner and group names 
     struct passwd *pw = getpwuid(fileStat.st_uid); 
     struct group *gr = getgrgid(fileStat.st_gid);  
     if (pw != 0) strcat(toRtn, pw->pw_name); 
     strcat(toRtn, " "); 
     if (gr != 0) strcat(toRtn, gr->gr_name); 
     strcat(toRtn, " "); 

     //filesize 
     strcpy(tmp, " "); 
     sprintf(tmp, "%ld", fileStat.st_size); 
     strcat(toRtn, tmp); 
     strcat(toRtn, " "); 

     //last access time 
     strcpy(tmp, " "); 
     strftime(tmp, 200, "%b %d %H:%M", localtime(&fileStat.st_atime)); 
     strcat(toRtn, tmp); 
     strcat(toRtn, " "); 

     //file/dir name 
     strcat(toRtn, dptr->d_name); 
     strcat(toRtn, " "); 

     //strcpy(contents[cnt], toRtn); 
     contents[cnt] = toRtn; 
     printf("%s\n", contents[cnt]); 

     strcpy(toRtn, " "); 
     cnt++; 
    } 
    return cnt; 
} 

私は

printf("%s\n", contents[cnt]); 

から行を取得し、出力は次のようになります。

drwxr-xr-x 30 justin justin 4096 Nov 22 20:18 .. 
drwxr-xr-x 2 justin justin 4096 Nov 22 20:18 . 
-rw-r--r-- 1 justin justin 5676 Nov 22 20:18 ls.c 
-rwxr-xr-x 1 justin justin 12172 Nov 22 20:18 ls 

が、私は

for (int i = 0; i < cnt; i++) 
{ 
    printf("%s ", contents[i]); 
} 

を印刷するときには何も表示されません。 私はstrcpy(content、toRtn)を使用しています。私はsegの欠陥を得る。

+0

'char tmp [sizeof(long int)];'が小さすぎる可能性があります。 'sizeof'は" 10進表現のバイト数+1 " –

+0

' strftime(tmp、200、 ')もバッファオーバーフローする可能性があります。 –

+0

' content [cnt] = toRt​​n; 'は悪いです。' toRt​​n '関数が返ってきたら破棄されますので、呼び出し元が値を調べると値が定義されていません –

答えて

0

理由は、さまざまな値がcntであるためです。

contents[cnt] = toRtn; 

toRtnは関数内のローカル配列で呼び出し元に(間接的に)戻りtoRtnするために使用されているので、場合関数が戻る存在しなくなります。ループ

for (int i = 0; i < cnt; i++) 
{ 
    printf("%s ", contents[i]); 
} 

繰り返しもはや存在charの配列の内容を印刷しようとする発信者のために、手段

。これは未定義の動作をもたらします。

コードには他にも基本的な懸念事項があります。ポインタと配列の関係をよりよく理解する必要があります(ある状況では互換的に使用できますが、コードの中には互換性がない場合は互換性があります)。スコープの意味(ローカル変数のアドレスを変数を含む関数/スコープが終了したときに変数が存在しなくなるため、呼び出し元は、いかなる手段によっても悪い考えです)。

0

このコードには多分エラーがあります。ここでは目に余るエラーです:

toRtn[0] = ((S_ISDIR(fileStat.st_mode)) ? 'd' : '-'); 
// WAIT what about the NUL terminator? 
strcat(toRtn, (fileStat.st_mode & S_IRUSR) ? "r" : "-"); 

別のエラーはここにある:

contents[cnt] = toRtn; 

のでcontents内のすべてのエントリはtoRtnを指します(つまりcontents[0] == contents[1]私はあなたが望むものではないと確信しています)これらはすべてポインタがつまらない(これもあなたが望むものではない)。

これらのエラーを修正することから始めます。

+0

whileループが実行されるたびにtoRtnは変更されませんか? – shadowguard

+0

@shadowguard:内容は変わりますが、配列自体(したがってそのアドレス)は常に同じです。 –

関連する問題