2017-12-27 18 views
1

この機能が登場したとき、私は"Understanding and Using C Pointers"のページを読んでいた。ダブルポインタ

void safeFree(void **pp) { 
    if (pp != NULL && *pp!= NULL) { 
    free(*pp); 
    *pp = NULL; 
    } 
} 

し、それからのコード例:

int main(int argc, char **argv) { 
    int* pi = (int*)malloc(sizeof(int)); 
    *pi = 5; 
    safeFree((void**)&pi); 

    return EXIT_SUCCESS; 
} 

私のポイントは、ifpp != NULLをチェックしていますこのシナリオの条件は無用ですよね?このコードが書かれているように、この条件は決して偽ではないからです。しかし、**ppがメモリアドレスを想定し、変数のメモリアドレスが決してNULLになることはないと仮定すると、この条件が真となるシナリオがありますか?あるいは誰かがこのようなことをした場合に作家がその検査をしたか?

int main(int argc, char **argv) { 
    int **pi = NULL; 
    safeFree((void**)pi); 

    return EXIT_SUCCESS; 
} 

ありがとう。

+1

*またはライターはケースの誰かで検診がこのような何かをしたことをやったやった*はい?それはまさにそのためです。関数を書くときは、例えばライブラリを書く場合など、関数のユーザではないかもしれないことに注意してください。特にポインタを扱うときは、明示的に 'NULL'をチェックし、それに応じて反応させるのが良いでしょう。 – Pablo

+0

はい、逆参照する前にポインタの値を確認してください。 'NULL'ポインタを渡すと' free'は無害ですが、ポインタへのポインタもチェックしてください。 catchは最初のポインタで、逆参照した場合には 'NUL'が失敗します。 –

+0

この関数はポインタを解放し、*をNULLに設定します*。これはダブルフリーを避ける方法です。 –

答えて

0

これは、safeFreeがちょうど混乱していると言いますが、ではなく、が安全です。このコードでは、APIユーザーが常に構築されたポインタを渡すと仮定しているためです。これらを考慮してください。

トリッキー0(ネジアップa)の

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


void safeFree(void **pp) { 
    if (pp != NULL && *pp!= NULL) { 
     free(*pp); 
     *pp = NULL; 
    } 
} 

int main() { 
    int *a; 
    int **p; 
    a = malloc(5 * sizeof(int)); 
    p = malloc(1 * sizeof(a)); 
    a[0] = 10; 
    p[0] = a; 
    fprintf(stderr, "%d\n", a[0]); 
    safeFree((void **)p); /* grrrr */ 
    fprintf(stderr, "%d\n", a[0]); 
} 

トリッキー1(クラッシュ)

int main() { 
    int a[] = { }; 
    int b[] = { 1 }; 
    int c[] = { 2 }; 

    int **p = malloc(3 * sizeof(int *)); 
    p[0] = a, p[1] = b, p[2] = c; 

    safeFree((void **)p); /* grrrr */ 
} 
+0

あなたのシナリオは理にかなっていません。 –

+1

はい、そうではありません、それはまさにポイントです! safeFreeプロトタイプの問題は、APIユーザーを混乱させるということです。誤解を招く可能性があることを示すために、やや無意味なシナリオを作成しました。 safeFreeの* safe *という単語は、APIユーザーが間抜けの割り当て解除要求を正しく処理できると考えるよう誤解しています。ここでは、mallocが誤って処理されていた(愚かではありますが)いくつかのケースがあります。 –

0

この関数は、主に2番目の場合のようにNULLをチェックします。実際の変数アドレスが渡された場合、そのチェックは失敗することはありませんが、あなたの呼び出し元がまともではないと信じることはありません。

関連する問題