0

同じディレクトリに保存されている特定の拡張子(* .bob)のファイルのリストに対していくつかの操作を行う必要があります。ファイルは画像フレームであり、名前の形式はframe_XXXX.bobです。先験的にフレーム数がわからないので、フレーム0から最後のフレームまで順番に処理する必要があります。でフォルダの内容を読み取りますがstruct dirent *readdir(DIR *dirp)、ファイルがアルファベット順に読み取られるとは限らないため(常にそうであるように見えますが)、ファイルを1つのリンクリストに入れてから、さらに処理する前に並べ替えます。 。リストの先頭を保存してから、ポインタに入力しますfilesListStart、次にフォルダの内容全体を読み取り、拡張子が「.bob」の場合は各エントリをリストに追加します。これはすべて、最大100フレームの場合にうまく機能しますが、何らかの理由でそれを超えると、ポインタがfilesListStart指す値にリストの最初のエントリのファイル名が含まれなくなります。コードは数字を使用していないので、100個を超える要素を超えることの意味がわかりません。filesListStartリストへの入力を開始する前と後のメモリアドレスを書き出しました。これらは同じですが、表示される値が魔法のように変化します。filesListStartフィールドが「frame_0000.bob」に等しいオブジェクトを指すように設定するとfileName(これは予想どおりです)、リストにデータを入力すると、指す名前は「e_0102.bob」になります。

リスト構造は次のように定義されます

// List structure
struct FilesList {
  char *fileName ;
  struct FilesList *next ;
} ;

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

DIR *moviesDir ;
moviesDir = opendir("movies") ;

if(moviesDir == NULL)
{
  printf("Make Movie failed to open directory containing bob frames\n") ;
  return ;
}

struct dirent *dirContent ;

// Get first .bob frame name from the directory
dirContent = readdir(moviesDir) ;
// isBobFile(dirContent) returns 1 if entry has ".bob" extension and 0 otherwise
while( !isBobFile(dirContent) )
{
  dirContent = readdir(moviesDir) ;
}

struct FilesList *filesList = (struct FilesList*)
    malloc( sizeof(struct FilesList) ) ;

// Initialize the list start at that first found .bob frame
filesList->fileName = dirContent->d_name;
// And save the head of the list
struct FilesList *filesListStart = filesList ;
printf("FilesListStart: %s\n", filesListStart->fileName) ;
printf("Address is: %p\n", filesListStart) ;

// For all other bob frames
while( (dirContent = readdir(moviesDir) ) != NULL )
{
  if( isBobFile(dirContent) )
  {
    struct FilesList *temporaryNode = (struct FilesList*)
        malloc( sizeof(struct FilesList) );
    temporaryNode->fileName = dirContent->d_name ;
    filesList->next = temporaryNode ;
    filesList = temporaryNode ;
  }
}
// Set the 'next' pointer of the last element in list to NULL
filesList->next = NULL ;
// close stream to directory with .bob frames
closedir(moviesDir) ;

// Check what FilesListStart points at
printf("FilesListStart: %s\n", filesListStart->fileName) ;
printf("Address is: %p\n", filesListStart) ;

// Rest of the code
4

1 に答える 1

2

実際の値を使用するのではなく、のコピーを作成する必要があります。dirContent->d_name

ランタイムライブラリは、dirent呼び出すたびにその構造の内容を自由に変更readdirできます。保存したのがアドレスだけの場合は、基になるメモリが変更される可能性があります。POSIXのマンページから:

readdir()によって返されるポインターは、同じディレクトリー・ストリーム上のreaddir()への別の呼び出しによって上書きされる可能性のあるデータを指します。

つまり、次の行を置き換えます。

filesList->fileName = dirContent->d_name;
temporaryNode->fileName = dirContent->d_name ;

と:

filesList->fileName = strdup (dirContent->d_name);
temporaryNode->fileName = strdup (dirContent->d_name);

あなたが-のような関数を持っていて、そうでなければ、ここでstrdup安く手に入れることができると仮定します。

100回の呼び出し後にのみ変更される場合は、ランタイムがもう少しインテリジェントにしようとしている可能性がありますが、無限の数を格納できないため、おそらく妥当な制限が設定されています。

リンクリストノードを解放する前に、これらすべてのcharポインタを解放することを忘れないでください(おそらくその「残りのコード」セクションのどこかにあります)。

于 2012-08-01T06:04:22.603 に答える