2013-07-29 3 views
10

私はリチャード・リースの(2013年5月)の新しいオライリーの本読んで「理解をし、Cポインタを使用する」、と私はその中のいくつかのコードについて質問があり、87ページreallocの後に元のポインタを使用していますか?

if (++length > maximumLength) { 
    char *newBuffer = realloc (buffer, maximumLength += sizeIncrement); 

    if (newBuffer == NULL) { 
     free (buffer); 
     return NULL; 
    } 

    currentPosition = newBuffer + (currentPosition - buffer); 
    buffer = newBuffer; 
} 

に私はの名前を願っていました。変数は自明である。コンテキストが必要な場合は、この抜粋だけでなく、コード全体を提供するように編集します。

私の質問は、currentPosition = newBuffer + (currentPosition - buffer);という行についてです。 realloc()の私の理解は、新しい割り当てが成功すると、最初に割り当てられたメモリが解放されることです。それが正しければ、問題の行は、ぶら下がっているポインタ、innitを使用していますか?その式のRHS上のbuffercurrentPositionは両方とも、解放されたメモリへのポインタです。

私の本能は、後でlengthを使用して、ぶら下がっているポインタを使用しないようにこれを書き直すことです。私はこれらの最後の2行を置き換えたい:二つのポインタはまだ(ごみのいえ)のアドレスを保持するために書かれた作品として、おそらくしかし

buffer = newBuffer; 
currentPosition = buffer + length; 

、コード、およびこれら二つのアドレス間のオフセットはまだのように計算することができますcurrentPositionを再割り当てする方法。だから私はこれについて不安を感じるだけで辛抱強く思っていますか?

質問を一般化するには:一度ポインタがぶら下がっている場合、オフセットの計算など、目的に応じてポインタに含まれているアドレスを使用しても安全ですか?ありがとう。

+0

再割り当て時に、 'length'はバッファのサイズ(調整前の' maximumLength')より1大きいです。意味を正しく解釈するには 'currentPosition = buffer + length - 1'を使うべきです。 – Casey

+0

実際に質問を投稿する前に確認しました。本のコードは 'length'と' currentPosition'の両方を0に初期化します。 'length'は最初の条件でインクリメントされるので、常に最後に追加された要素のインデックスを1回通過します。 'currentPosition'は、新しい要素が追加される場所であり、追加の後に増加します。これはどのようにコードを記述したのではなく、与えられたコードを取って、 'buffer + length'が正しいものです。 – verbose

+0

したがって、 'currentPosition'はあらかじめ構成された' buffer + length'ですか?私は訂正されています(そして、冗長性に少し驚いています)。 – Casey

答えて

9

一度ポインタがぶら下がっている場合、オフセットの計算など、ポインタに含まれているアドレスを使用するのは安全ですか?

いいえ、安全ではありません。 freeの後、ポインタ値は無効なアドレスであり、無効なアドレスは未定義の動作を呼び出さずにポインタ演算に使用できません。

+0

ソース?私はこれを期待していないだろう。 –

+2

@CoryNelson C11、6.5.6p8ポインタ演算。結果が配列オブジェクトにない場合、または最後の要素を過ぎた場合=>未定義の動作。 – ouah

+1

@Ouah、私はあなたが結果を間接参照しようとするときを指していると思います。 – ROTOGG

0

ポインタを逆参照しようとしない(つまり、演算子*を適用する)限り、ダングリングポインタ(たとえば、ポインタ演算)を使用しても安全です。

+3

これは間違っています。なぜなら、C標準では、もはや存在しないオブジェクトへの以前のポインタの算術演算が保証されないからです。ポインタがメモリアドレスとして実装されていて、アドレスの算術演算が動作するのは明らかですが、ポインタは必ずしもそのように実装されているわけではありません。さらに、オプティマイザはCのルールに基づいて控除を行うことが許可されており、驚くべき動作につながる可能性があります。 –

関連する問題