4

アプリケーションの実行中に更新する必要のあるいくつかの共有ライブラリで構成されるプラグインがアプリケーションにあります。パフォーマンス上の理由から、古いプラグインをアンロードする前に新しいプラグインをロードして使用を開始し、すべてのスレッドが古いプラグインの使用を完了した場合にのみ、プラグインをアンロードします。新しいプラグインと古いプラグインのライブラリには同じシンボルが含まれているため、をdlopen()使用しRTLD_LOCALます。新しいプラグインが誤って内部関数から古いプラグインのシンボルを呼び出さない場合。

プラグインの1つのライブラリは、プラグインのdynamic_cast()別のライブラリによって作成されたオブジェクトに対して実行されます。これは、HP-UX、AIX、Solaris、およびWindowsで機能しますが、Linuxでは機能しません。私が理解できる限り、これは、これらすべてのOS(コンパイラ)がクラスの名前を使用して(内のdynamic_cast())型を比較しているのに対し、Linuxは名前文字列アドレスを使用してこの比較を行っているため(パフォーマンスを向上させるため)、各ライブラリには独自のライブラリがあるためです。type_infoオブジェクト(でロードされたためRTLD_LOCAL)アドレスが異なるため、等しいタイプは。と等しくないようdynamic_cast()です。

次のいずれかを行う方法はありますか?

  • 提供されたかのように、オブジェクトのみtype_infoがロードされるようRTLD_GLOBALにします。
  • コンパイラーにtype_info、タイプ間の比較にアドレスではなくクラス名の比較を使用させる。

?使用しているコンパイラは次のとおりです。

$ icpc -V
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.0.084 Build 20101006
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.
4

2 に答える 2

5

わかりました、私たちが最終的にやったことは、問題を回避することです。

必要なクラスにdynamic_cast()2 つの静的関数を追加しました。

static MyClass* doNew();
static MyClass* doDynCast(MyBase*);

これらは cpp ファイルに実装されておりnew、 、 、dynamic_cast()およびtype_infoオブジェクトが同じ lib に保持されていたためdynamic_cast()、問題が回避されていました。

この解決策は私たちの特定のケースには十分でしたが、より一般的な解決策がある場合は歓迎されます。

私たちが見つけた別のオプションは、クラスのすべての実装を cpp ファイルに配置することです。これにより、typeinfoシンボルが 1 つのライブラリにのみ存在し、他のすべてのライブラリがそれを参照するだけになります。これにより、 が成功しdynamic_cast()ます。

于 2011-05-24T13:53:07.517 に答える
3

残念ながら、type_info 構造体は、それらを作成するライブラリにローカルな弱いシンボルであるため、簡単に機能させることはできませんdynamic_cast。ただし、クラス vtable (および type_info) がインスタンス化される場所を操作してみてください。GCC では、クラス内の最初の非インライン関数 (定義順)が共通の共有依存関係ライブラリでのみ定義されるようにすることで、これを行うことができます。クラスに非インライン関数がない場合は、この生成を​​強制するためだけにダミーを作成します。ただし、これをテストしていないため、動作することを保証できないことに注意してください。さらに、これはコンパイラに依存します。Intel のコンパイラが何をするのかわかりません。

もちろん、代わりにクラス名を使用して独自の代替動的キャスト メカニズムを実装することもできます。Qt のqobject_castなど、これを行うライブラリも多数あります。

于 2011-05-24T20:12:46.703 に答える