5

関数に値でポインタを渡すと、次のように関数内でポインタを解放できないことが知られています。

void func(int *p)
{
    free(p);
    p = NULL;
}

pは(おそらく有効な)アドレスのコピーを保持しているので、free(p)はそれを解放しようとします。しかし、それはコピーであるため、実際にそれを解放することはできません。free()の呼び出しは、実際には解放できないことをどのようにして知るのでしょうか。

上記のコードはエラーを生成しません。つまり、free()は、引数として渡されたアドレスを処理できないことを「どういうわけか」知って、黙って失敗するということですか?

4

5 に答える 5

21

pは(おそらく有効な)アドレスのコピーを保持しているので、free(p)はそれを解放しようとします。しかし、それはコピーであるため、実際にそれを解放することはできません。

それは真実ではない。が(または)によって返された有効なアドレスであるfree()場合は、正常に機能します。pmalloc()NULL

実際、これはカスタムの「デストラクタ」関数を実装するための一般的なパターンです(CでOOスタイルのコードを作成する場合)。

おそらくあなたが意味するのは、それはこの後pは変わらないというNULLことです-しかし、あなたはそれを価値によって渡しているので、それは自然なことです。free() ポインタを無効にしたい場合は、ポインタ( "byref")で渡します。

void func(int **p)
{
    if (p != NULL) {
        free(*p);
        *p = NULL;
    }
}

そしてこれを次のように使用します

int *p = someConstructor();
func(&p);
// here 'p' will actually be NULL
于 2012-12-18T17:20:27.243 に答える
2

唯一の問題は、この関数が別のDLL(Windows)にあるかどうかです。次に、標準ライブラリの異なるバージョンとリンクされ、ヒープの構築方法について異なるアイデアを持つことができます。

それ以外は問題ありません。

于 2012-12-18T17:21:46.653 に答える
2

値による受け渡し。これpによりfunc()、ポインタがコピーされfunc()、メモリを解放するローカルコピーが作成されます。func()次に、ポインタの独自のインスタンスをに設定しますpNULL、これは役に立ちません。関数が完了すると、パラメーターpは存在しなくなります。関数の呼び出しでは、アドレスを保持するポインターがまだありますpが、ブロックは現在フリーリストにあり、再度割り当てられるまでストレージには役立ちません。

于 2012-12-18T17:28:02.887 に答える
1

誰もが言っていることは、あなたのメモリはによって解放されるfree(p);が、あなたの元のポインタ(あなたが関数を呼び出すために使用する)はまだ(現在は無効な)アドレスを保持しているということです。アドレスを含む新しいメモリブロックが元のポインタよりも後の段階で割り当てられた場合(メモリマネージャの場合)、完全に異なるデータを指すようになり、あらゆる種類の問題と混乱が発生します。

于 2012-12-18T17:50:41.077 に答える
0

いいえ、あなたは本当にメモリのブロックを解放します。関数呼び出しの後、この関数に渡されたポインターはどこも指していません:同じアドレスですが、MMUはこのアドレスをどうするかをもう知りません

于 2012-12-18T17:21:37.293 に答える