5

が再割り当てされないように見えるのはなぜresultですか?

  while (loc) {
    char nextLine[MAX_PATH_LEN + 30];
    sprintf(nextLine, "%s:%d\n", loc->item.pathname, loc->item.offset);
    DPRINTF('h', ("got next line\n"));
    while (spaceUsedUp + strlen(nextLine) > allocatedSize) {
      allocatedSize *= 2;
    }
    if (realloc(result, allocatedSize) == NULL) {
      perror("realloc");
    }
    DPRINTF('h', ("Next line length is %d\n", strlen(nextLine)));
    DPRINTF('h', ("Allocated size is %d\n", allocatedSize));
    DPRINTF('h', ("The size of the result is %d\n", strlen(result)));

    strcat(result, nextLine); // THIS LINE CAUSES THE BUFFER OVERFLOW                         

    spaceUsedUp += strlen(nextLine);
    DPRINTF('h', ("SpaceUsedUp is %d\n", spaceUsedUp));
    loc = loc->nextLocation;
  }

出力は次のとおりです。

got next line
Next line length is 21
Allocated size is 100
The size of the result is 0
SpaceUsedUp is 21
got next line
Next line length is 21
Allocated size is 100
The size of the result is 21
SpaceUsedUp is 42
got next line
Next line length is 21
Allocated size is 100
The size of the result is 42
SpaceUsedUp is 63
got next line
Next line length is 21
Allocated size is 100
The size of the result is 63
SpaceUsedUp is 84
got next line
Next line length is 21
Allocated size is 200
The size of the result is 84
*** buffer overflow detected ***: ./proj3/disksearch terminated
4

4 に答える 4

6

realloc によって返された結果を破棄しています。その値を に割り当てる必要がありますresult。典型的な使用法は次のようになります。

if ((tmp = realloc(result, allocatedSize)) == NULL) {
      perror("realloc");
      /* more error handling here, including (usually) freeing result or exiting */
} else {
      result = tmp;
}
于 2012-12-05T18:05:06.797 に答える
4

reallocは、再割り当てされたバッファーへのポインターを返し、元のバッファーを解放する場合があります。この意味は

if (realloc(result, allocatedSize) == NULL)

バッファを効果的に破棄し、解放された可能性のある古いバッファを使用したままにするため、間違っています。表示されている問題は、バッファ オーバーフローそのものではありません。代わりに、割り当てられていないメモリに書き込もうとした結果、未定義の動作が原因でクラッシュが発生します。

コードを次のように変更できます

void* tmp = realloc(result, allocatedSize);
if (tmp != NULL)
    result = tmp;
else    
    perror("realloc");
于 2012-12-05T18:05:30.810 に答える
0

realloc() の戻り値の型は、requirement にキャストされる void* です。そして、このポインターは、割り当てられたサイズの新しいメモリを指します。理想的には、realloc は 4 つの操作を行います。

  1. 指定されたサイズの新しいメモリを作成します。
  2. 古いメモリから新しいメモリにコンテンツをコピーします。
  3. 古いメモリを解放します
  4. 新しいメモリのアドレスを返す
于 2012-12-05T18:18:59.590 に答える
0

マンページが大好きです。人生の答えはすべてそこにあります...とにかく重要なものです。

戻り値
malloc() および calloc() 関数は、任意の種類の変数に適切にアラインされた、割り当てられたメモリへのポインタを返します。エラーの場合、これらの関数は NULL を返します。サイズがゼロの malloc() の呼び出しが成功した場合、または nmemb またはサイズがゼロの calloc() の呼び出しが成功した場合も、NULL が返されることがあります。free() 関数は値を返しません。

realloc() 関数は、新しく割り当てられたメモリへのポインタを返します。これは、あらゆる種類の変数に対して適切に配置され、 ptr とは異なる場合があり、要求が失敗した場合は NULL になります。size が 0 の場合、NULL または free() に渡すのに適したポインターが返されます。realloc() が失敗した場合、元のブロックはそのまま残ります。解放または移動されません。

ご覧のように、強調表示された部分のためにmalloc()'s friendrealloc()がマニュアル ページに唯一のエントリを取得します。返される値は、realloc()渡されたメモリへの参照とは異なる場合があります。これは重要な注意事項です。

したがって、ここのコードでは:

if (realloc(result, allocatedSize) == NULL) {
  perror("realloc");
}

あなたは本当に気にかけている結果を無視しています。チェックNULLは良いですが、いくつかの一時変数に割り当ててからチェックする必要があります。
(一時変数に代入する理由もマニュアルページにあることに注意してrealloc()ください。失敗した場合resultでも、上書きしない限りバッファは良好です)

于 2012-12-05T18:30:19.163 に答える