4

「モデル」を作成するコードに取り組んでいます。モデルは XML ファイルから作成され、その表現の一部はオンザフライで生成される C コードです。この C コードは、(POCO 共有ライブラリ クラスを使用して) 動的に読み込まれる共有ライブラリにその場でコンパイルされます。共有ライブラリには主に小さな関数が含まれており、モデル作成の一部は、これらの関数への関数ポインターを設定することです。これはすべて正常に機能します。ただし、複数のモデルを同時に作成すると問題が発生します。

これは、Linux での動的ロードの仕組みと、各共有ライブラリに同じ名前の関数が含まれているという事実に関係していると思います。PICが原因ですか?問題は、共有ライブラリ関数からデータを取得することで明らかになります。

問題は、同一の関数名を含む複数 (数千) の共有ライブラリを Linux にロードする方法です。

上記は、動的にロードされたライブラリのデータ/関数が互いに完全に分離されているように見えるウィンドウで正常に機能します。

4

2 に答える 2

3

Poco SharedLibrary の open 関数はリンカー フラグを受け入れます。デフォルトは、dlopens RTLD_GLOBAL に対応する Poco::SharedLibrary::SHLIB_GLOBAL と、RTLD_LOCAL に対応する Poco::SharedLibrary::SHLIB_LOCAL です。詳細については、 http://linux.die.net/man/3/dlopenを参照してください。

Poco::SharedLibrary::SHLIB_LOCAL フラグを渡すと、問題が修正されました。

于 2013-02-28T20:46:50.380 に答える
3

まず、dlopen何十万もの共有オブジェクトを作成できます。私のmanydl.cはそれを示しています。

次に、C コードの生成、コンパイル、およびdlopen共有オブジェクトをすべて同じプロセスから行うこともできます。私の(2017年に廃止された)MELTプラグイン(GCCの場合、MELTはGCCを拡張するための高レベル言語を提供します)はそれを行います(私のmanydl.c例もそうです)。

ただし、同じ(定義済みの)関数名をそれらに保持する必要はないと思います。それを避けることをお勧めします。あなたは出来る

  1. 一意の名前を生成します (C コードが生成されるため、これが最適で、最も移植性が高く、最も単純なソリューションです)

  2. -Dこれらの名前にいくつかのフラグを#define付けて一意の名前にコンパイルすると、ソース コードに明らかに重複した名前が含まれる可能性があります。つまり、生成されたコードが、それをコンパイルするコマンドに a (グローバルに一意である) をfoo渡す関数を定義している場合です。(もちろん、あなたはそれから)。-Dfoo=foo_123foo_123gccdlsym"foo_123"

  3. 生成されたコードにvisibility("hidden")関数属性を追加します。-fvisibility=hidden オプションを に渡すこともできますgcc

  4. 静的関数のみを持ち(名前はあまり重要ではないため、重複する可能性があります)、constructor何らかの方法で関数をバインドする関数を持ちます(たとえば、ポインターをどこかに、たとえばグローバルテーブルに保存します)。

  5. dlopen(3)RTLD_LOCALに渡すことを検討するかもしれません。それが良いアイデアかどうかはわかりません (そして、POCO はおそらくその方法を知りません)。

PS。私はそれが位置に依存しないコードに関連しているとは思わない(共有オブジェクトでは望ましいが、絶対に必要というわけではない;多くの非効率な再配置を行う必要がない) -fPICdlopenこれは、Linux 共有オブジェクトのリンクとロードに関連しています。詳細については、 Levine の Linkers & Loaders bookを参照してください。

この質問も参照し、共有ライブラリの作成方法に関するDrepperの論文を読んでください。

于 2013-02-28T18:31:08.193 に答える