3

私は多くの静的ライブラリを持っています。1つはstatic_lib_a.aです。ダイナミックライブラリdynamic_lib.soを作成して、それらをまとめます。

static_lib_a.aでは、xerces3.1.1を使用してxmlを解析します。以下は、 static_lib_a.aのコードスニペットです。

xerces::DOMElement *pElementNode = dynamic_cast<xerces::DOMElement *>(pNode);

pNodeのタイプはxerces::DOMNodeです。xerces::DOMElementのオブジェクトに割り当てられます。このコード行はダウンキャストを実行します。

dynamic_lib.soでstatic_lib_a.aのすべてのシンボルを非表示にするために、-fvisibility=hiddenを使用してこの静的ライブラリを構築します。--fvisibility = hiddenを追加すると、pElementNodeは実行時にNULLポインターを返すことがわかりました。

gccコンパイラのバージョンは3.4.4です。

誰かが以前に同様の問題を抱えていますか?

4

3 に答える 3

3

問題の原因は、 gcc wikiの「C++ 例外に関する問題」というタイトルのセクションで説明されています。そこにある「漠然としたリンケージ」リンクをたどり、仮想テーブルとtypeinfoのセクションを読んでください。

xerces::DOMNodeクラスとxerces::DOMElementには非純粋で非インラインの仮想関数が含まれていないため、これはすべてあなたのケースに当てはまります(実際、これらのクラスは完全にヘッダーに含まれています)。これは、いずれかのクラスの仮想テーブルが、ヘッダーを含むすべてのオブジェクト ファイルに出力されることを意味します。

dynamic_cast が適切に機能するために必要ないずれかのクラスの typeinfo シンボルは、仮想テーブルと同じオブジェクト、つまりヘッダーを含むすべてのオブジェクト ファイルに出力されます。

ライブラリに非表示の可視性をマークするxerces::DOMNodexerces::DOMElement、static_lib_a.a のオブジェクトのすべての typeinfo シンボルが非表示にマークされました。wikiページが指摘しているように、これにより、リンカーがそれをdynamic_lib.soで非表示としてマークし、dynamic_castが失敗することが保証されます。

于 2011-05-13T23:28:21.403 に答える
1

非表示の可視性を使用することは、ライブラリが特定のアクセス ポイント経由でのみ使用されるようにするための優れた方法です。ライブラリが外部でどのように使用されているかを正確に把握しているため、ライブラリを変更する場合、これは非常に有利です。

これは、DLL のアクセス可能な部分の一部を declspec にする Windows と非常によく似た手法ですが、インポートまたはエクスポートする場合は記述しないというわずかな違いがあり、ライブラリが「可視」関数を作成している可能性があります。実装するのではなく使用します。

あなたの質問に答えるために、可視性はバージョン 4 以降でのみサポートされていると思います。確かに、ここではこれを使用します

#if defined(__GNUC__) && __GNUC__ >= 4

非表示の可視性を使用する場合、どのシンボルを表示したいかを明示的に述べる必要があります。したがって、これがあります:

__attribute__((visibility("default")))

おそらく、より読みやすいものに #define するでしょう。おそらく SO_EXPORT です。

#define SO_EXPORT __attribute__((visibility("default")))

定義クラス:

class SO_EXPORT MyAccessInterface;

そして次のようなメソッド:

SO_EXPORT int doSomething( parameters );

実際には、非表示の可視性のための同様のマクロもあります (上記と同様ですが、「デフォルト」ではなく「非表示」です)。したがって、プロジェクト全体に「デフォルト」の可視性を使用する場合でも、実装の詳細を隠すことができます。

#define SO_HIDDEN __attribute__((visibility("hidden")))

class SO_HIDDEN MyClassImpl;

于 2011-02-25T11:59:06.747 に答える
0

dynamic_cast派生クラスの typeinfo ノードが基本クラスの typeinfo ノードを指す必要があります。これは、動的再配置によって行われます。typeinfo ノードのシンボルが表示されない場合、派生クラスのノードを含むモジュールには独自のコピーがあり、dynamic_cast はこれらのクラスが別個のツリーからのものであると想定し、キャストを許可しません。

デフォルトの可視性を宣言する属性を基本クラス定義に追加する必要があります。

于 2011-02-25T12:21:39.670 に答える