2016-03-24 6 views
-1

は、このプログラムを考えてみましょう:Cでクリーンアップを行う別の方法は?

int main(void) 
{ 
    int* i = malloc(sizeof(int)); 
    int* j = malloc(sizeof(int)); 
} 

mallocが失敗し、ポインタがfree D」ではありませんので、しかし、これは、単純なアプローチです。

だから、これを行うことができます。

int main(void) 
{ 
    int* i; 
    int* j; 

    if ((i = malloc(sizeof(int)) < 0) 
    { 
     return -1; 
    } 
    if ((j = malloc(sizeof(int)) < 0) 
    { 
     free(i); 
     return -1; 
    } 

    free(i); 
    free(j); 
} 

を、私はこの非常にエラーが発生しやすい考えるが。最後にmallocのエラーの場合は、ポインタを20個割り当てなければならないと考えると、freeの変数とreturn -1が必要です。

私も、私はこのようにそれを書くために助けることができる、atexitを知っている:優れている

int* i; 
int* j; 

void del_i(void) 
{ 
    free(i); 
} 

void del_j(void) 
{ 
    free(j); 
} 

int main(void) 
{ 
    if ((i = malloc(sizeof(int)) < 0) 
    { 
     return -1; 
    } 
    else 
    { 
     atexit(del_i); 
    } 

    if ((j = malloc(sizeof(int)) < 0) 
    { 
     return -1; 
    } 
    else 
    { 
     atexit(del_j); 
    } 
} 

が、私はグローバルとしてすべてのポインタを宣言する必要が嫌い。これら二つのアプローチを組み合わせることがいくつかの方法は基本的には、次のとおりです。

  1. を直接実行することができますいずれか、またはatexitで使用するポインタ、のデストラクタを持ちます。
  2. 関数に対してローカルのポインタを持つ。
+0

私はあなたのポイントを得ることはありません。あなたがプログラムの実行を終了/停止しているなら、なぜ 'free()'について気にしますか? –

+0

1.常にポインタをフリーズしてください。 2.大きなプログラムの中でこれを考えてください – hgiesel

+0

私に教えていただきありがとうございますが、私は私のバージョンに固執します。 :) –

答えて

0
int main(void) 
{ 
int* i = NULL; // Init with NULL otherwise free on none NULL possible 
int* j = NULLL; 

if (!(i = malloc(sizeof(int))) 
{ 
    goto exit; 
} 
if (!(j = malloc(sizeof(int))) 
{ 
    goto exit; 
} 
... 
exit: 
    free(i); 
    free(j); 
    ... 
    return err; 
} 

これは、あなたがのgoto文で解決することができるものです。失敗した場合に

if ((i = malloc(sizeof(int)) < 0) 
{ 
    return -1; 
} 

malloc戻りNULL、ない負の数:

+2

割り当てが成功すると 'exit'にジャンプします。それほど役に立たない。 – unwind

+0

はい、私の金庫はそれを忘れてしまったのです! – Schafwolle

+1

http://www.dwheeler.com/essays/apple-goto-fail.htmlタイプの間違いにちょうど注意してください。 – Tommy

3

まず、これはmalloc障害を検出しません。

第2に、atexitは、静的およびグローバルオブジェクトをクリーンアップするのに適しています。ローカルオブジェクトをグローバルにすることは、atexitの内部でのみ使用することをお勧めします。

より良いアプローチは、すべてまたは何もない単位で割り当てる必要のあるすべての関連ポインターを作成し、すべてを一度に解放する関数を定義し、それらを1つずつ割り当てる関数を作成することですメモリは、各割り当てにチェックして:NULL

typedef struct AllOrNothing { 
    double *dPtr; 
    int *iPtr; 
    float *fPtr; 
    size_t n; 
} AllOrNothing; 

void freeAllOrNothing(AllOrNothing *ptr) { 
    free(ptr->dPtr); 
    free(ptr->iPtr); 
    free(ptr->fPtr); 
    free(ptr); 
} 

int allocateAllOrNothing(size_t n, AllOrNothing **res) { 
    *res = malloc(sizeof(AllOrNothing)); 
    if (*res == NULL) { 
     return -1; 
    } 
    // Freeing NULL is allowed by the standard. 
    // Set all pointers to NULL upfront, so we can free them 
    // regardless of the stage at which the allocation fails 
    (*res)->dPtr = NULL; 
    (*res)->iPtr = NULL; 
    (*res)->fPtr = NULL; 
    (*res)->n = n; 
    (*res)->dPtr = malloc(n*sizeof(double)); 
    if ((*res)->dPtr == NULL) { 
     free(*res); 
     *res = NULL; 
     return -1; 
    } 
    (*res)->fPtr = malloc(n*sizeof(float)); 
    if ((*res)->fPtr == NULL) { 
     free(*res); 
     *res = NULL; 
     return -1; 
    } 
    (*res)->iPtr = malloc(n*sizeof(int)); 
    if ((*res)->iPtr == NULL) { 
     free(*res); 
     *res = NULL; 
     return -1; 
    } 
    return 0; 
} 
4

freeはノーオペレーション安全であると定義されます。だから、非ジャンプの変化は次のようになります。

int *i = malloc(sizeof(int)); 
int *j = malloc(sizeof(int)); 

if(i && j) 
{ 
    // do some work 
} 

free(i); 
free(j); 
0
int main(void) 
{ 
    int* i = NULL; 
    int* j = NULL; 
    bool success = false; 

    do { 
     i = malloc(sizeof(int)); 
     if (NULL == i) break; 

     j = malloc(sizeof(int)); 
     if (NULL == j) break; 

     success = true; 
    } while (0); 

    if (!success) 
    { 
     printf("Something failed!"); 
    } 
    else 
    { 
     printf("All succeeded!"); 
     // Do more work 
    } 

    free(i); 
    free(j); 
    return (success? 0 : 1); 
} 
-1
int *i=NULL,*j=NULL; 

    if(!(i=malloc(sizeof(int)))) 
      goto EXIT; 
    if(!(j=malloc(sizeof(int)))) 
      goto EXIT; 
    /* do some work */ 
    return 0; 
    EXIT: 
      free(i); 
      free(j); 
      exit(EXIT_FAILURE); 

後藤が悪いプログラミングの練習 考えられているが、ここで私たちは私たちのタスクは、使いやすさとシンプルさ

0

で行わ得るためにそれを使用することができますが、複数の出口点を避ける。割り当てとエラー処理の交錯を避けてください。きれいな操作順序に従います。

  1. リソースの宣言、割り当て、初期化を行います。
  2. すべて成功した場合は、タスクを実行します。
  3. クリーンアップ。
  4. 返品ステータス。

// Do all allocations first, test their `NULL`-ness, then free them all. 
int main(void) { 
    // Allocate resources 
    // declare and allocate in one step 
    int* i = malloc(sizeof *i); 
    double* j = malloc(sizeof *j); 

    // Test for acceptability 
    bool ok = i && j; 

    // Perform the main body of code 
    if (ok) { 
     ; // do normal process in the code; 
    } 

    // free resources 
    free(i); 
    free(j); 

    // return status 
    return ok ? 0 : -1; 
} 
関連する問題