5

C では、関数が動的に割り当てられたメモリへのポインターを返し、呼び出し元のコードがそれを解放する必要がある可能性があります。また、呼び出し元のコードが 2 番目の関数にバッファーを提供し、そのバッファーの内容を設定する必要があることもよくあります。例えば:

struct mystruct {
   int a;
   char *b;
};


struct mystruct *get_a_struct(int a, char*b)
{
    struct mystruct *m = malloc(sizeof(struct mystruct));
    m->a = a;
    m->b = b;

    return m;
}

int init_a_struct(int a, char*b, struct mystruct *s)
{
    int success = 0;
    if (a < 10) {
        success = 1;
        s->a = a;
        s->b = b;
    }

    return success;
}

どちらかの方法が望ましいですか?両方の引数を考えることができます。get_a_struct メソッドの場合、返された構造体をfree()するだけでよいため、呼び出しコードが単純化されます。init_a_struct メソッドの場合、呼び出し元のコード自体がおそらくメモリを割り当てているため、呼び出し元のコードが動的に割り当てられたメモリの解放に失敗する可能性は非常に低くなります。

4

4 に答える 4

4

特定の状況にもよりますが、一般的には、割り当てられたバッファを提供することが望ましいようです。

Jim が述べたように、呼び出された関数がメモリを割り当てると、DLL が問題を引き起こす可能性があります。これは、コードを DLL として配布することを決定し、get_a_struct がエクスポートされ、DLL のユーザーに表示される場合に当てはまります。次に、ユーザーは、できればドキュメントから、解放、削除、またはその他の OS 固有の機能を使用してメモリを解放する必要があるかどうかを判断する必要があります。さらに、正しい関数を使用してメモリを解放したとしても、別のバージョンの C/C++ ランタイムを使用している可能性があります。これにより、見つけにくいバグが発生する可能性があります。このRaymond Chen の投稿を確認するか、「メモリ割り当て dll 境界」を検索してください。典型的な解決策は、DLL から独自のフリー関数をエクスポートすることです。したがって、get_a_struct/release_a_struct というペアが作成されます。

一方、呼び出された関数だけが、割り当てる必要があるメモリの量を知っている場合があります。この場合、呼び出された関数が割り当てを行う方が理にかなっています。それが不可能な場合、たとえば DLL 境界の問題が原因で、典型的な解決策は、この情報を見つけるメカニズムを提供することです。たとえば Windows では、パラメータとして 0 と NULL を渡すと、GetCurrentDirectory関数は必要なバッファ サイズを返します。

于 2013-07-23T16:49:10.740 に答える
1

ほとんどの場合、呼び出しコードで malloc/calloc を呼び出す必要がないため、既に割り当てられている構造体を引数として提供することが望ましいと思います。したがって、それを解放することを心配します。例:

int init_struct(struct some_struct *ss, args...)
{
    // init ss
}

int main()
{
    struct some_struct foo;
    init_struct(&foo, some_args...);
    // free is not needed
} 
于 2013-07-23T01:01:24.710 に答える
1

なんらかのロジスティック上の理由で、すべてのオブジェクトが「ヒープから割り当てられた新しいオブジェクト」であることが絶対に必要でない限り、「ポインターを渡すことをお勧めします」-たとえば、ノードとしてリンクされたリストに入れられ、リンクされた-リストハンドラーは、最終的に free を呼び出すことによって要素を破棄します-または、「ここから作成されたすべてのものはfree後で行く」という他の状況)。

malloc可能であれば、「呼び出さない」ことが常に推奨される解決策であることに注意してください。malloc呼び出しに時間がかかるだけでなくfree、割り当てられたメモリのどこかで呼び出す必要があり、割り当てられたすべてのオブジェクトが数バイト (通常は 12 ~ 40 バイト) の「オーバーヘッド」を必要とするため、小さなオブジェクトにスペースを割り当てます。絶対に無駄です。

于 2013-07-23T01:12:31.663 に答える