2

暗号化タスクを実行するアプリケーションを開発しています。これらのタスクには OpenSSL を使用し、インターフェイスは のインターフェイスに似ていますlibcurl。よくわからない場合は、次のようになります。

conf_func(handle, ENUM_OPTION, value);

したがって、インスタンスでENUM_OPTIONtoで表されるオプションを設定します。それのドキュメントを読むと、すべての値がコピーされ(特に明記されている場合を除く)、したがって割り当てたものを解放し、割り当てたものを解放すると書かれています。valuehandlelibcurl

これは私のアプリケーションで行うには良い考えかもしれないと思いました。必要なメモリ量は増えますが、確実に使いやすくなります。しかし、ここで問題に直面します。次のコードを想定します。

X509 *cert = X509_new();
X509 *cert_copy = malloc(sizeof(X509));
memcpy(cert_copy, cert, sizeof(X509));

もちろん、これは問題を引き起こします。これは浅いコピーにすぎず、解放すると問題が発生します。検索した結果、ディープ コピーは OpenSSL によってネイティブに提供されておらず、望ましくない可能性がある (メモリ使用量) と判断しました。

したがって、私は別のアプローチを取りました: 渡されたポインターをコピーするのではなく、保存するだけです。

X509 *cert = X509_new();
X509 *cert_copy = cert;
X509_free(cert_copy);

これにより、メモリ フットプリントが削減され、開発が容易になります。一方、これは文書化の必要性と特別な使用法への認識を高めます: あなたが割り当てますが、私はあなたのために無料で提供します.

それで、私はこの動作を一貫して提供する必要があると思いましたか? しかし、その後、文字列に問題が発生します。

char *s = "Some text";
char *s_copy = s;
free(s_copy);

これsは定数であり、ヒープに割り当てられていないため機能しません。

したがって、私のジレンマがあります。文字列をコピーする必要がありますが、OpenSSL 構造体をコピーする必要はありません。これをきれいに解決するにはどうすればよいですか?それを文書化し、ユーザーがインターフェースを正しく使用することに頼っていますか? それとも、私が見逃している完全に明白なものがありますか?

: 私を解放するということは、使用の最後に一般的な破棄機能があることを意味します。それ以外の場合は、ポインターがNULL解放されているかどうかを確認するだけです。

4

1 に答える 1

2

あなたが発見したように、そのライブラリがコピーを実行するためのAPIを公開しない限り、ライブラリに属する​​不透明なデータオブジェクトを「ディープコピー」する正しい方法はありません。いくつかのオプションがあります:

  1. ライブラリに属する​​オブジェクトを呼び出し元に渡すのではなく、そのオブジェクトを作成するために必要な情報/パラメーターを渡すだけです。次に、コードでライブラリを自由に呼び出してオブジェクトを作成します。

  2. コードが渡されたオブジェクトの "所有者" になるようにインターフェイス コントラクトを設計し、呼び出し元はそれらを渡した後にそれらを使用してはなりません。

  3. 呼び出し元とコードの間で所有権が明確に共有されるように、インターフェイス コントラクトを設計します。これは、たとえば、コードがまだオブジェクトへの参照を持っている間、呼び出し元がオブジェクトを変更または解放しないことを意味しますが、コードがそのオブジェクトの使用を終了した後、呼び出し元はそれを自由に使用でき、解放する責任があります。

どのアプローチが最適かは、アプリケーションの要件によって大きく異なります。メモリやパフォーマンスが重大な問題でない限り、私は単純さを優先する設計を選択します。

于 2013-04-12T19:00:43.503 に答える