15

これが標準的な動作にならない理由はfree()何ですか?

同じオブジェクトを指す複数のポインター:

#include <stdlib.h>
#include <stdio.h>

void safefree(void*& p)
{
    free(p); p = NULL;
}

int main()
{
    int *p = (int *)malloc(sizeof(int));
    *p = 1234;
    int*& p2 = p;
    printf("p=%p p2=%p\n", p, p2);
    safefree((void*&)p2);
    printf("p=%p p2=%p\n", p, p2);
    safefree((void*&)p); // safe

    return 0;
}

mallocからキャストされた要求からの割り当てvoid*

逆に:

safefree()void*&(参照)にキャストされた要求

4

9 に答える 9

28

もしそうなら、あなたは関数へのポインタへのポインタを渡さなければならないでしょう:

int * p = malloc( sizeof( int ));
free( & p );

多くの人が間違えると思います。

于 2010-04-16T09:37:33.133 に答える
27

簡単な答え:式を解放している可能性があるためですfree(find_named_object("foo"))

詳細:このfree関数は、void*解放するメモリのアドレスであるパラメータを取ります。これは、アドレスを提供した元の変数の知識(または、さらに言えば、変数が存在するかどうか)を関数に付与するものではありません。渡されたパラメータをNULLに設定するだけでは、アドレスのローカルコピーであるため、何も実行されません。

于 2010-04-16T09:35:32.263 に答える
15

演算子がオペランドをゼロにする必要があるかどうかを議論するdeleteBjarneStroustrup 。これはfree()関数ではありませんが、とにかく良い議論です。次のような点を考慮してください。

  • free(p + 1)と言ったら、何がゼロになりますか?
  • メモリへのポインタが2つある場合はどうなりますか?ぶら下がっている参照がまだ残っている場合、なぜ1つだけをnullに設定するのですか?

彼はまた、それは意図されていたが、決して起こらなかったと言いますoperator delete

C ++では、削除の実装で左辺値のオペランドをゼロにすることが明示的に許可されており、実装でそれができることを期待していましたが、そのアイデアは実装者に普及していないようです。
于 2010-04-16T10:35:16.227 に答える
6

C関数のパラメーターは常に値で渡されるため、free()に渡されるポインターを変更するには、割り当てが解除されているポインターにポインターを渡す必要があります。これにより、演算子の忘れによるバグが発生する可能性があります。

次に、そのポインターにエイリアスが含まれている場合でも、プログラマーはそれらを無効にする責任があります。すべての参照がNULLに設定されていると想定して、プログラマーによって引き起こされる問題を確認できました。

最後に、ポインタをNULLに設定する必要は必ずしもありません。いくつかのメモリを割り当て、いくつかの作業を行い、戻る前にそれを解放する関数を想像してみてください。ポインタをNULLに設定するのが最適ではないように見えるかもしれません。

于 2010-04-16T09:50:00.943 に答える
5

関数パラメータはCの値で渡されるためです。つまり、p == 0x12345の場合、p "itself"ではなく'0x12345'をfree()に渡します。

于 2010-04-16T09:37:48.247 に答える
2

Cでは、関数を呼び出しても、渡したパラメーターの値を変更することはできません。そのため、の値をに設定してfree(p)変更した場合、この動作は実際には非常に非標準になります。pNULL

于 2010-04-16T09:38:41.293 に答える
2

削除に関するStroustrupからの引用を参照して、PeterNorvigも同様の発言をしています。彼は次のように書いています(C ++についてではありません!):

"Nothing is destroyed until it is replaced"
 - Auguste Comte (1798-1857) (on the need for revolutionary new
   theories (or on the need to do x.f = null in garbage-collected
   languages with destructors))

私のCコードでは、次のマクロが非常に便利です。

#define free(p) free((void *)(p)),(p)=NULL /* zero p */

これは、書かれているように、その引数を2回使用します。ただし、free(p ++)やfree(find_named_object( "foo"))などの使用法ではコンパイル時エラーが発生するため、これは問題ではありません(左辺値が必要です)。また、(free)(p ++)を使用するか、FREEなどの別の名前でマクロを非表示にすることができます。

于 2010-04-16T17:21:24.037 に答える
0

int *&からへの参照のキャストは、機能することvoid *&が保証されていません。 int *と同じサイズ、表現、または位置合わせの要件を持つ必要はありませんvoid *

Neil Butterworthがコメントで示唆しているように、適切なC++ソリューションはテンプレートを使用することです。そして、これらの方法はどちらもCでは機能しませんfree()

于 2010-04-16T23:37:27.810 に答える
0

ゼロのこのマニアックなことは何ですか?他にも数字があります!

フリーポインタに他の識別値よりもゼロを多く含める必要があるのはなぜですか?

実際には、私のC ++コードでは、ウォッチドッグオブジェクトを使用することが多く、ポインターを解放すると、ポインターをゼロではなくウォッチドッグにリセットします。これには、オブジェクトのメソッドを既存のインターフェイスで呼び出すことができ、ポインタをゼロにリセットするよりもはるかに安全で効率的であるという追加の利点があります(オブジェクトのゼロのテストを回避し、オブジェクトを呼び出すだけです)。

free like関数がzfree(void *&p)がpをゼロに設定すると言う場合、それは私のウォッチドッグスタイルを禁止します(または少なくとも助けにはなりません)。

そして、他の人が指摘しているように、それがスコープ外になった場合にポインターをゼロにリセットするポイントは何でしょうか?ただ役に立たないコード。また、同じアドレスなどを含む他のポインタがある場合はどうなりますか。

于 2010-07-13T11:18:46.323 に答える