5

ピア コード レビュー セッション中に、次のようなコードを見ました。

char *s = new char[3];
*s++ = 'a';
*s++ = 'b';
*s++='\0';
delete []s; // this may or may not crash on some or any day !!

まず、標準 C++ では、配列サイズの 1 つ前を指すことは問題ありませんが、アクセスすると未定義の動作が発生することを知っています。だから、最後の行*s++='\0'は大丈夫だと思います。しかし、私の記憶が正しければ、C++ 標準では、返さdeleteれたのと同じポインターを提供する必要があると規定されています。new

これは、返されたポインターが改ざんされてはならないことを意味すると私は信じています。new使用する可能性のある返されたアドレスの前にハウスキーピング情報を保持する可能性があるためだと思いdeleteます。new'd ポインターを移動すると、これにアクセスできなくなる可能性があります。

それは未定義の動作ですか、それとも実装定義または未指定ですか? 誰でもこれを確認できますか?できれば、C++ 標準の正しい場所を指すことによって。

ドラフト C++ 標準 (Draft_SC22-N-4411.pdf) の自由に利用できるドラフト バージョンでは、セクション 5.3.5 に詳細が記載されています。Bjarneさんのホームページから頂きました。

4

3 に答える 3

17

C++ 標準のセクション 5.3.5/2 から:

delete のオペランドの値は、前の配列 new 式から得られたポインター値でなければなりません。そうでない場合、動作は未定義です

于 2009-04-25T07:59:03.787 に答える
4

はい、[] new によって与えられた元のポインターを削除する必要があります。この場合、それは配列の末尾ではなく先頭へのポインターになります。ここのコードは、他の不特定のランダム オブジェクトを削除しています。

于 2009-04-25T07:54:12.940 に答える
3

ええ、これがよく実装される方法を思い出してください: new は実際に malloc を呼び出し、これは へのポインターを返します(void*)(&(((int*)p)[1]))。ここで、p は割り当てられたメモリの実際の開始点であり、最初の int は返された実際のメモリのサイズです。

返されるポインタは、割り当てられた実際のメモリのさらに 1 つの sizeof(int) (または任意のアライメントが必要) です。オブジェクトをそこに置き、実際のサイズはそのままにします。

次に、そのポインターが delete に渡され、free に渡されると、free は、渡されたポインターの 1 つの int を調べて、返されているサイズを見つけます。

私たちが得たもの以外のものを返すということは、 free が任意の量の実際のメモリが返されていると考えていることを意味し、それに応じて空きリストを台無しにします。

繰り返しになりますが、これはよく実装される方法であり、new、delete、malloc、または free を実装する必要がある方法ではありません。

于 2009-05-01T03:21:08.430 に答える