0

こんにちは、ファイルを PFS イメージにパックする必要があるプロジェクトに取り組んでいます。ANSI C 言語を使用してアプリケーションを作成しています。各ファイルのHexdumpおよびその他の属性を取得し、変数内に保存しています。

パックされるファイルに関するすべての情報が収集されたら、各ファイルの情報を含む出力ファイルを作成する必要があります。

これを行っていると、メモリ割り当てに問題があります。エラーを出力するコードは次のとおりです。

for (Counter = 0; Counter < PackingCount; Counter ++)
{
    PFSEntry Packed;

    Packed.HexEquivalent = DumpHex(FileNames[Counter]);

    strncpy(Packed.Filename, FileNames[Counter], NAME_BLOCK);

    Packed.Offset = OffsetCounter;

    OffsetCounter += FileSize;

    Packed.FileSize = FileSize;

    Packed.Timestamp = 2999606509; // For the Sake of Diffing

    Packer[Counter] = Packed;


}

上記のループが満たす構造を以下に示します

typedef struct
{
 char Filename [NAME_BLOCK];
 u_int32_t Timestamp;
 u_int32_t Offset;
 u_int32_t FileSize;
 char * HexEquivalent;
} PFSEntry;

DumpHex 関数は次のとおりです。

char * DumpHex(char * FileName)
{
   FILE *  File = FileOpener(FileName, "rb");

   printf("%s is of Size %ld\r\n\r\n", FileName, FileSize);

   fseek(File, 0L, SEEK_END);

   FileSize = ftell(File);

   fseek(File, 0L, SEEK_SET);

   char * HexArray = malloc(FileSize);

   unsigned char Character;

   int Counter = 0;

   while (Counter < FileSize)
   {
       Character = fgetc(File);     
       sprintf(HexArray  + Counter, "%c", Character);       
       Counter++;
   }

   return HexArray;
}

指定されたファイルの 16 進出力を返す関数 DumpHex は、次のエラーを出力しています。

a.out: malloc.c:2369: sysmalloc: アサーション `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2]))) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size)

= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1)) ) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' 失敗しました。中止 (コアダンプ)

以下は、解決策を見つけるのに役立つアプリケーションに追加されたデバッグ情報です。

Total Files to Pack 38 
Size of Packed Structure 80
Packing File 0 of size 9319 Bytes
Packing File 1 of size 1459 Bytes
Packing File 2 of size 844 Bytes
Packing File 3 of size 4396 Bytes
Packing File 4 of size 270250 Bytes
Packing File 5 of size 656800 Bytes
Packing File 6 of size 0 Bytes
Packing File 7 of size 322744 Bytes
Packing File 8 of size 1278114 Bytes
Packing File 9 of size 12473 Bytes
Packing File 10 of size 13791 Bytes
Packing File 11 of size 14158899 Bytes
Packing File 12 of size 343051 Bytes
Packing File 13 of size 599051 Bytes
Packing File 14 of size 505867 Bytes
Packing File 15 of size 10138349 Bytes
Packing File 16 of size 17481 Bytes
Packing File 17 of size 4900 Bytes
Packing File 18 of size 9000 Bytes
Packing File 19 of size 343 Bytes
Packing File 20 of size 6888 Bytes
Packing File 21 of size 13992 Bytes
Packing File 22 of size 916222 Bytes
Packing File 23 of size 2048 Bytes
Packing File 24 of size 7776 Bytes
Packing File 25 of size 13884 Bytes
Packing File 26 of size 10787 Bytes
Packing File 27 of size 12747 Bytes

a.out: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) 
&((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) &&
old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof
(struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 *
(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end &
pagemask) == 0)' failed.

中止 (コアダンプ)

私はこの言語に不慣れで、メモリ割り当てとフリーメソッドの概念をよく理解していません。

4

1 に答える 1

1

ここに示されているコードから、エラーを考えると、malloc 自身のデータ構造を破壊している範囲外の配列アクセスがどこかにあるようです。

一部のファイルで動作するという事実は、まったくの幸運です。これは、未定義の動作の問題です。期待どおりの動作は、未定義の動作の一種です。これが、このようなバグを追跡するのを難しくしている理由です。

私がここで見ることができることから、これは間違っています:

   while (Counter < FileSize)
   {
       Character = fgetc(File);     
       sprintf(HexArray  + Counter, "%c", Character);       
       Counter++;
   }

HexArray動的に割り当てられたFileSizeバイト配列です。ただし、sprintf()出力文字列は常に null バイトで終了することに注意してください。したがって、反復ごとに、HexArray[Counter]が に設定されCharacterHexArray[Counter+1]がヌル バイトに設定されます。最後の反復を除いて、これに害はありません。Counter(FileSize-1最後の反復) の場合、sprintf()null バイトが書き込みされますHexArray[FileSize]-範囲外の access。これは未定義の動作であり、malloc データ構造が破損する可能性が高く、プログラムの後半で不可解なエラーが発生します。

の各位置に文字を書きたいだけの場合はHexArray、はるかに効率的でエラーが発生しにくい形式を使用できます。

   while (Counter < FileSize)
   {
       Character = fgetc(File);
       HexArray[Counter++] = Character;
   }

また、Characterはであるため、からにunsigned char変更する必要があります。HexArraychar *unsigned char *

巨大なファイルで何が起こるかも考慮してください (プログラムが巨大なファイルで呼び出されることになっている場合)。組み込みシステム向けに開発している場合は特に、メモリの枯渇は現実です (これは事実のようです)。

于 2014-02-24T21:55:33.950 に答える