9

ファイルのリストを char** 変数に保存しようとしています。

scandir() は正常に終了しますが、char** を印刷しようとするとセグメンテーション違反が発生します。

コードは次のとおりです。

int main()
{
    char** fileList;
    int noOfFiles;
    char* path = ".";
    makeList(&fileList, &noOfFiles, path); 
    return 0;
}

void makeList(char ***fileList, int* noOfFiles, char* path){
    struct dirent **fileListTemp;
    *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);
    int i;
    fileList = (char***)malloc(sizeof(char***));
    *fileList = (char**)malloc(*noOfFiles * sizeof(char*));
    printf("total: %d files\n",*noOfFiles);
    for(i = 0; i < *noOfFiles; i++){
        *fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name) *sizeof(char));
        strcpy(*fileList[i], fileListTemp[i] -> d_name);
        printf("%s\n",*fileList[i]);
    }
    return;
}

これにより、2 つのファイル名を出力した後にセグメンテーション違反が発生します。

出力:

合計: 27 ファイル。

..

.jv

セグメンテーション違反 (コアダンプ)

4

4 に答える 4

22

関数scandir()がメモリを割り当てます。

メモリを割り当てる必要はありません。によって返されたメモリを解放する必要がありますscandir()

あなたのコードは以下を呼び出します: *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);

返されると、ディレクトリnoOfFiles内のディレクトリ エントリの数が含まれ、割り当てられたstruct dirent blobへの割り当てられたポインタの配列を指します。各 blobには、ファイル/ディレクトリの null で終わる名前を指すd_nameメンバーがあります。pathfileListTemp

たとえば、ディレクトリに「FirstFile.txt」、「AnotherFile.txt」、「ThirdFile.txt」というファイルが含まれている場合、呼び出しで から戻るとscandir()、3 つのファイルに対して5noOfFilesに設定され、「 ." および「..」ディレクトリエントリ。「alphasort」を通過しない場合、エントリは特定の順序にはなりません。(実際には少し間違っています。ファイルが最初に作成された順序に依存するディレクトリファイル名エントリの順序になります。)

「alphasort」を渡したので、次の順序でエントリが表示されるはずです (null-byte-string-terminator を明示的に表示しています:

fileListTemp[0]->d_name == ".\0"
fileListTemp[1]->d_name == "..\0"
fileListTemp[2]->d_name == "AnotherFile.txt\0"
fileListTemp[3]->d_name == "FirstFile.txt\0"
fileListTemp[4]->d_name == "ThirdFile.txt\0"

したがって、fileListTemp は、5 つのstruct direntポインターを保持する割り当てられたメモリのブロックを指します。5 つのstruct direntポインターのそれぞれは、 d_nameメンバーに null で終わるディレクトリ エントリ名を含む、割り当てられたメモリのstruct direntブロックを指します。(d_name エントリもポインタであるため、これも単純化されていますが、割り当てられたブロックの最後に余分に割り当てられたスペースを指し、そこにエントリ名が格納されます。)

つまり、割り当てられたメモリの 6 ブロックです

この割り当てられたメモリは、使い終わるまで使用できます。その後、配列内の各エントリで free() を呼び出し、続いて配列自体の free() を呼び出します。

配列自体だけでなく、すべてのエントリを解放する必要があります。それらはすべて、独立して割り当てられたメモリのブロブです。

リストが完成したら、次のことを行う必要があります。

for (int i = 0; i < noOfFiles; i++)
  {
  free(fileListTemp[i];
  }

free(fileListTemp);
于 2014-02-07T00:32:05.267 に答える
0

これが問題かどうかはわかりませんが、null 終端用に別のバイトを割り当てる必要があります。

*fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name + 1) *sizeof(char));
于 2013-08-23T12:14:10.067 に答える