web-dev-qa-db-ja.com

ポインターがCですでに解放されているかどうかを確認する方法は?

ポインターが既に解放されているかどうかを確認したいと思います。 gnuコンパイラセットを使用してこれを行うにはどうすればよいですか?

28
Kitcha

できません。これを追跡する方法は、0またはNULLを解放した後、ポインターを割り当てることです。しかし、Fred Larsonが述べたように、これは同じ場所を指している他のポインターには何もしません。

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;
30
Chad

できません。 NULLの後にfreeを割り当てるだけで、2回解放しないようにできます(free(NULL)で問題ありません)。

さらに良いのは、可能であれば、すでに解放したコードを「忘れる」ことはしないでください。

編集

質問をポインタが指すメモリがすでに解放されているかどうかを調べる方法:として解釈することはできません。あなたはあなた自身の簿記をしなければなりません。

26
cnicutar

Gregがコメントしたように、ポインターが解放されたかどうかを確認する信頼できる方法はありません。解放されたメモリは他の無関係なデータによって占有され、誤った結果が得られます。

実際、ポインタが解放されているかどうかを確認する標準的な方法はありません。 つまり、glibcには、ポインターのmallocステータスを見つけるための関数(mcheckmprobe)があります- ヒープ一貫性チェック .

ただし、、これらの関数は主にデバッグのみに使用され、 スレッドセーフではありません要件が不明な場合は、これらの関数を避けてください。malloc/freeがペアになっていることを確認してください。 。


http://ideone.com/MDJkj

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

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}
14
kennytm

NULLを割り当てるマクロを作成することにより、NULLをポインター値に割り当てる概念を拡張できます。例えば:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

その後、コードがfree()ではなくFREE()のみを使用することを確認する限り、作成したコードが同じメモリを2回解放しないことを確信できます。もちろん、それはメモリを解放するライブラリ関数への複数の呼び出しを妨げるものではありません。また、すべてのmallocに空きがあることを保証するものではありません。

関数でこれを試みることはできますが、参照演算子をスローする必要があり、通常のfree()の呼び出しのようには見えないため、扱いにくくなります。

5
Brian McFarland

できないので、あなたはしません。

malloc()から取得したポインターを追跡し、それらを一度だけ解放します。

使用する場合、メモリにはメモリがないため、メモリが割り当てられているかどうかはわかりません。 OSのメモリマネージャーのみがそれを知ることができます(ただし、Cにはこの情報を照会するための標準化されたメカニズムは含まれていません)。

2
Kerrek SB

この答えはa little bit遅くなりましたが、私は この回答 を読み、次のことを確認するコードを書きました。

Freeは、メモリブロックを独自のフリーブロックリストに配置します。通常、アドレス空間内の隣接するブロックを一緒に結合しようとします。空きブロックリストは、メモリチャンクの単なる循環リストであり、最初に管理データが含まれています。空きリストは最初の場所でもあり、mallocは必要なときに新しいメモリチャンクを探します。 OSから新しいメモリを呼び出す前にスキャンされます。必要なメモリより大きいチャンクが見つかると、2つの部分に分割されます。 1つは呼び出し元に返され、もう1つはフリーリストに戻されます。

このコードは、割り当てられた最初のポインターが解放された場合にのみチェックします。

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

HP-UXとLinux Redhatでこのコードをテストしましたが、ポインターが1つしかない場合に機能します。

0
Mansuro