C/C++free(NULL)の思考

2857 ワード

最近code reviewの时に1段のmagic codeを発见して、freeの指针はNULLを指して、その时胆戦心は惊いて、第1の反応はfreeの1つの空の指针がNEを引き起こすことができて、double freeの1つの住所と同じ効果であるべきです.しかし、落ち着いて、このコードは古いコードで、しかもずっと実行されていると思って、問題ないはずです.そうしないと、とっくに暴露されています.
C標準ライブラリfreeを調べると以下の説明があります.
**Description The C library function void free(void ptr) deallocates the memory previously allocated by a call to calloc, malloc, or realloc. Declaration Following is the declaration for free() function. void free(void ptr) Parameters ptr —— This is the pointer to a memory block previously allocated with malloc, calloc or realloc to be deallocated. If a null pointer is passed as argument, no action occurs. Return Value This function does not return any value.
もしfreeが空のポインタを持っていたら、何も起こらなかっただろう.double freeのポインタとは違います.だから、ポインタを明記するときは、char*str=NULLなどの初期値NULLを付与したほうがいいです.後でうっかりfreeしても問題はありません.free 1枚のmallocのポインタの後、ポインタをNULLにする必要があります.double freeを避けることができます.free 1枚のmallocのポインタをNULLにするのは符号化ルールが要求すると思っていたが,今では実用的な意味がある.現在メンテナンスされているcodeには、以下のようなcodeが大量に含まれています.実はこのような書き方もdouble freeを避けることができません.freeの後にポインタをNULLにしていないからです.
if (pointer != NULL) {
    free(pointer);
}

次の書き方がいいです.
if (pointer != NULL) {
    free(pointer);
    pointer = NULL;
}

しかし、freeの前にpointerがNULLかどうかを判断するたびに、あまりよくない感じがします.freeの後にpointerをNULLに設定し、定義ポインタにNULLを付与する習慣を身につけていれば、判断条件はremoveできます.
{
    free(pointer);
    pointer = NULL;
}

参考までにsampleを書きます.
typedef struct {
    int id;
    cahr* str;
} TestParam;

void testFree(int id) {
    TestParam *testParam = NULL;
    testParam = (TestParam*)malloc(sizeof(TestParam));
    if (testParam == NULL) {
        return;
    }
    memeset(testParam, 0, sizeof(TestParam));
    testParam->id = id;
    testParam->str = NULL;
    // testParam->str              malloc     ,     。
    //   testParam->str    malloc   ,       free  ,  testParam->str    NULL。            free     NULL   。
    free(testParam->str);
    testParam->str = NULL;
    free(testParam);
    testParam = NULL;
}

一つのプロジェクトは一人で開発するわけではないので、知識の準備が違うかもしれません.私たちは自分を厳しく要求するしかありません.freeの場合はNULLかどうかを判断し、freeの後にNULLを置く必要があります.ポインタを明示するときの初期値をNULLにします.最後のcodeは、一般的には次のように書かれています.
if(testParam != NULL) {
    if (testParam->str != NULL) {
        free(testParam->str);
        testParam->str = NULL;
    }
    free(testParam);
    testParam = NULL;
}

またfreeのポインタはmalloc,calloc or reallocの3つの割り当てられたメモリポインタに限られる.ローカルポインタchar str[]=「abcdef」を自分で定義した場合.free(str)なら、何もできないはずだと推測しますが(undefined behavior occurs)、free(NULL)と同じように、構造とmallocの構造が違うので、もちろんこのようなことは避けなければなりません.free mallocのメモリが1枚あると、このメモリは未知で、元の値を維持したり、割り当てられたりする可能性があります.この場合、再びfreeは深刻な問題を引き起こします(undefined behavior occurs).
プログラミングは本当に学問に限りがなく、少しずつ蓄積し、好奇心と学習の心を維持するしかない.簡単なものを思えば考えるほど、含む知識は豊かになる.