5

のオーバーロードnewdelete演算子の方法dll。オーバーロードされた演算子を dll の一部として記述しましたが、これとリンクするクライアントdllは使用しませんoverloaded new and delete

4

2 に答える 2

9

セクション 17.6.4.6/3 で、C++ 標準がこれについて述べなければならないことを次に示します。

プログラムの (new / delete 演算子の) 定義は、実装によって提供されるデフォルト バージョンの代わりに使用されます。このような置換は、プログラムの起動前に行われます。プログラムの定義は、として指定してはなりませんinline。診断は必要ありません。

それを注意深く読むと、あなたが抱えている問題を正確に説明しています。ここで起こっているのは一種の「キャッチ 22」です。

一方では、オーバーロードされた new/delete を動的にリンクできないため、new/delete 演算子の定義を DLL 内でコンパイルすることはできません (これは、DLL をロードする前の静的初期化中に new/delete が必要になる可能性があるためです。 DLL のロードの前後で一貫性のない new/delete 演算子があり、それは未定義の動作です)。

一方、新規/削除演算子の定義を DLL ヘッダー ファイルにそのまま配置することはできません。inlineこれは、One Definition Rule (ODR) を満たすためにマークを付ける必要があるためです。上記の条項。それらがマークされていないという要件inlineはおそらくそこにあります。マークされた関数定義inlineには「リンケージがない」ため、各翻訳単位は独自のコンパイル済みバージョンを使用する(またはインライン展開として)ため、通常は問題ありませんが、動的メモリ割り当て。

new上記の両方のキャッチは、正確さのために、一般に、割り当てられたメモリが対応する演算子で割り当て解除されることを保証する必要があるという事実によって動機付けられますdelete(つまり、いわば「一緒にコンパイル」、または両方がデフォルトになります)。たとえば、new/delete 演算子が基礎となる malloc/free 呼び出しに依存している場合、DLL と実行可能ファイルの間で、new/delete 演算子を呼び出した変換単位によって使用されるヒープに依存している場合、このヒープがは同じになります (実際、特に Windows ではそうではありません。2 つのモジュールは動的メモリ割り当てに 2 つの別々のヒープを使用します)。

したがって、Rookが言うように、あなたの問題の解決策は「それをしないでください」です. DLL オブジェクトの new/delete 演算子をオーバーロードしないでください。これを正しく実行するためのクリーンなメソッドがないためです。コードをひねったり変更したりしても、常に上記と同じ問題が発生します。

std::shared_ptr代わりにできることとすべきことは、DLL オブジェクトにファクトリ関数パターンを使用し、オブジェクトが作成されたサイトへの削除の動的なディスパッチに依存するカスタム デリーターを使用してスマート ポインター ( など) を返すことです。 . これはChad Austinのテクニックにインスパイアされています。私はここで非常に似たようなことをしました。

于 2012-08-07T14:26:45.470 に答える