0

何かのためにバッファを取り込む関数があり、関数のスコープ内のバッファにメモリを割り当てる必要があるとしましょう。次のようになります。

void func_with_buf( ...params..., char** buf ) {

    if ( !buf ) {
       buf = ( char** )calloc( ... );
    }

    /* more stuff here */
    ...
} 

さて、この関数の後半には、falseと評価される別の条件ステートメントがあります。if/条件ステートメントでfalseが返された場合bufは、関数自体でこれ以上何もできないため、ポインターからポインターを解放する必要があります。 。

したがって、これには2つのアプローチがあり、拡張性、再利用などの観点から、どちらが「より安全」でより実用的であると見なされるかを知りたいと思います。

アプローチA)

char* buf;

if ( !func_with_buf( ..., &buf ) ) {

   free( buf );
   buf = NULL;
   /* more error handling here */
}

アプローチB)

char* buf; 

if ( !func_with_buf( ..., &buf ) ) {
    /* no need to free buf because func_with_buf handles deallocation internally. */
} 

アプローチA)が推奨される方法であると何かが教えてくれますが、私は興味があり、何かを見落としたかどうかを確認したいと思います。

また、プログラマーがポインターからポインターを解放する必要がある場合、それを渡すだけで処理できるのと同じくらい簡単free(p)ですか?または、同じタイプの単一のポインターにキャストする必要がありますか?

非常に多くの質問...

4

2 に答える 2

4

アプローチ(C)

char* buf = func_with_buf( ..., buf );

このようにして、元のbufを渡しますが、新しいまたはbufを返します。問題が発生した場合は、NULLを返します(関数でクリーンアップします)。

于 2012-09-17T05:13:59.523 に答える
4

関数の説明で非常に明確にされていれば、どちらも許容できると思います。

個人的には、メモリを割り当てる機能があり、なんらかの理由で失敗した場合、そのメモリを解放する義務があると感じています。呼び出し元がメモリが役に立たないことを示すエラー状態を受け取った場合、呼び出し元はメモリも解放されたことを期待する必要があります。

言い換えれば、メモリは関数が成功を示した場合にのみ有効です。

ちなみに、あなたの関数ではこれを行っています:

buf = ( char** )calloc( ... );

しかし、私はあなたがこれをするつもりだったと思います:

*buf = ( char* )calloc( ... );

変更するポインタを提供するように呼び出し元に要求しています。したがって、ポインタをポインタに渡しましたが、必要な実際のデータ型はの配列ですchar

最後の質問(申し訳ありませんが、最初は表示されませんでした)については、いいえ、キャストする必要はありません(キャストする場合を除くvoid*)。この関数freeは、メモリアドレスを取得し、そこに割り当てられているメモリを解放します。タイプは必要ありません。

于 2012-09-17T05:09:57.087 に答える