1

以下のコードは、最初に1文字を割り当て、すでに持っているメモリが文字列を格納するのに不十分になるたびに割り当て量を2倍にすることにより、にbuffer = (char*) realloc(buffer, allocated * sizeof(char));スペースを動的に割り当てるために使用する呼び出し(下にマークされている)で失敗することがあります。char*

プロジェクトの他の多くの部分に非常によく似たコードがあり、メモリ割り当てポリシーと呼び出しは同じです (void*に渡すの型のみを変更しますrealloc)。

問題をデバッグするために VS2010 を使用しています。デバッグ モードでプログラムを起動すると、関数は常に正常に完了します。

ただし、コマンドラインからプログラムを呼び出す場合、realloc の呼び出しの 1 つが「アクセス違反の読み取り場所」エラーでしばらくして失敗する可能性があります。ただし、常に発生するわけではなく、以下の関数が複数回呼び出された後に発生し、多くの再割り当てが既に行われています。

さらに奇妙なことに、ポインターの位置が変更されたかどうかをアサートするための realloc 呼び出しの前後にいくつかのプリントを配置しました。そうしてプログラムを実行すると、realloc の呼び出しがランダムに失敗しなくなりました。

私は何を間違っていますか?

TOKEN
next_token_file(FILE* file, 
                STATE_MACHINE* sm, 
                STATE_MACHINE* wsssm)
{
    char* buffer = (char*) malloc(sizeof(char));
    size_t allocated = 1;
    size_t i = 0;
    while(1)
    {
    /*
    ... code that increments i by one and messes with sm a bit. Does nothing to the buffer.
    */
        // XXX: This fails when using realloc. Why?
        if(i + 1 >= allocated)
        {
            allocated = allocated << 1;
            buffer = (char*) realloc(buffer, allocated * sizeof(char));
        }
        buffer[i] = sm->current_state->state;
    /*
    ... more code that doesn't concern the buffer
    */
    }
    // Null-terminate string.
    buffer[++i] = 0;
    TOKEN t = {ret, buffer};
    return t;
}
4

3 に答える 3

4

これらの行のために

char* buffer = (char*) malloc(16 * sizeof(char));
size_t allocated = 1;

bufferプログラムは、最初の 4 回の再割り当てで縮小します。そのため、プログラムは割り当てられていないメモリに書き込みますがi=16、これは未定義の動作であるため、何かが起こる可能性があります。また、これはおそらくメモリ管理を破壊し、それがrealloc()失敗につながります。

これらの 2 行を次のように変更できます。

size_t allocated = 16; /* or = 1 if the 16 was a typo. */
char * buffer = malloc(allocated); 

その他の注意事項:

  • sizeof(char)は常に1
  • malloc/calloc/realloc必要でも推奨でもないため、結果をキャストしないでください: https://stackoverflow.com/a/605858/694576
  • システムコールの結果を確認してください。

最後のメモを参照して、次の変更を適用する必要があります

char * buffer = malloc(allocated); 

次のようになる可能性があります。

char * buffer = malloc(allocated); 
if (NULL == buffer)
{
  /* Error handling goes here. */
}

buffer = (char*) realloc(buffer, allocated * sizeof(char));

次のようになる可能性があります。

{
  char * pctmp = realloc(buffer, allocated);
  if (NULL == pctmp)
  {
    /* Error handling goes here. */
  }
  else
  {
    buffer = pctmp;
  }
}
于 2013-08-20T15:20:38.893 に答える