おかげで、それはライブラリは、そのサービスを使用しているアプリケーションを作る「契約」を文書化することが重要です。ライブラリライターは、ライブラリによって行われたすべての割り当てと、アプリケーションによって解放される必要があるものについて文書化します。どんな契約と同様、シンプルで一貫性があるのは良いことです。この特定のケースで
、私は、ライブラリも提供すべきであるとします構造体を解放します
void free_bs(bs *b)
{
if (b->d) {
/* free b->d here */
}
/* free rest of the structure */
}
を。ここでd配列を解放することも意味があります。アプリケーションはすべてのbs
構造体へのポインタを持ち、必要がなくなったときにfree_bs
を呼び出します。
たとえば、将来の使用のためにdを保持したい場合は、ライブラリ操作が完了した後、契約がもう少し複雑になります。ライブラリはまた、提供することができます:d
へのポインタを返し、自由なルーチンはそれをスキップするために知っているように、空のフィールドを残し
double** bs_get_data(bs *b)
{
double **d = b->d;
b->d = NULL;
return b->d;
}
を。
bs_get_data()
のドキュメントでは、1回だけ呼び出すことができ、この場合はアプリケーションが配列を解放する責任があることを説明する必要があります。
UPDATE:以下のあなたのコメントへの答えで :まず第一に、私は(少なくとも)次のことを仮定することによって、問題を単純化していることに注意してください。d
は、単一のbs
構造によって、またはアプリケーションのいずれかによって参照されています。アプリケーションとライブラリは、配列への単一の参照を相互に「渡し」ます。同じd
配列をより多くのbs
構造に入れたい場合は、私のアプローチでは十分ではありません。
コメント内で提案しているフラグは役に立つかもしれませんが、標準的な方法であるFWIKでは使用できません。この場合、私はいくつか簡単な参照カウントを実装することを提案します。 new_bs()
では1と
typedef struct {
double **d;
int ref;
} d_t;
初期ref
とd
の「コピー」を受信するすべての機能では、参照カウントをインクリメント:d
が周りに共有する必要があるリソースがある場合は、それを「オブジェクト」を作ります。 bs
構造体が削除されたり、アプリケーションにd
が不要になった場合は、参照カウントを減らしてください。ゼロになったら、解放してください。ある意味では、それは高水準言語があなたのために行うものであり、リソース管理を正常に保つ上で非常に効率的です。
だれも誰もアレイを所有していませんが、最後にそれを必要とする者は誰でもそれを解放します。
もちろん、これにより多くの作業が必要となり、コードが複雑になるため、バランスをとってみてください。それはあなたが持っているすべての構造に必要なわけではありませんが、複数の参照を保持する必要がある場合にのみ必要です。
出典
2009-08-05 23:03:52
tsg
超高速応答に感謝します。 ** dの所有権をフラグする "storageMode"(内部/外部)フィールドを含めることは意味がありますか? free_bsは、内部的に所有されている場合にのみ解放されます(b-> d)。これは、呼び出し元が** dを解放する責任があるという点で、契約を明示的にするでしょうか? 構造体内に共有オブジェクトを使用する際に別の問題がありますか? OOの人たちは、このような練習に嫌になるだろうと思う!!合理的な選択肢はありますか?データのコピーは必要ありませんか? もう一度ありがとう、tr – user151410
私は応答で私の答えを編集したので、私はもっと書くことができます:-)。要するに、参照カウントを考慮する必要があります。 – tsg