100

Ubuntu12.10でGCC4.7のlibstdc++を使用して構築されたC++アプリケーションを、かなり古いバージョンのlibstdc++が付属しているUbuntu10.04を実行しているシステムにデプロイする必要があります。

-static-libstdc++ -static-libgcc現在、このブログ投稿で提案されているように、私はコンパイルしています: libstdc++を静的にリンクします。著者は、libstdc ++を静的にコンパイルするときに、動的にロードされたC ++コードを使用しないように警告しています。これは、私がまだチェックしていないことです。それでも、これまでのところすべてが順調に進んでいるようです。Ubuntu10.04でC ++ 11の機能を利用できます。これは、私が求めていたものです。

この記事は2005年のものであり、それ以来、おそらく多くの変更が加えられていることに注意してください。そのアドバイスはまだ最新ですか?知っておくべき潜在的な問題はありますか?

4

5 に答える 5

147

そのブログ投稿はかなり不正確です。

私の知る限り、C ++ ABIの変更は、GCCのすべてのメジャーリリース(つまり、異なる第1または第2バージョン番号コンポーネントを持つリリース)で導入されています。

違います。GCC3.4以降に導入された唯一のC++ABIの変更は下位互換性があり、C++ABIはほぼ9年間安定しています。

さらに悪いことに、ほとんどの主要なLinuxディストリビューションはGCCスナップショットを使用したり、GCCバージョンにパッチを適用したりするため、バイナリを配布するときに処理している可能性のあるGCCバージョンを正確に知ることは事実上不可能です。

ディストリビューションのパッチが適用されたバージョンのGCCの違いはわずかであり、ABIは変更されません。たとえば、Fedoraの4.6.3 20120306(Red Hat 4.6.3-2)は、アップストリームFSF4.6.xリリースとほぼ確実に4.6と互換性があります。 x他のディストリビューションから。

GNU / Linuxでは、GCCのランタイムライブラリはELFシンボルバージョン管理を使用するため、オブジェクトやライブラリに必要なシンボルバージョンを簡単に確認できます。libstdc++.soこれらのシンボルを提供するがあれば、それが機能します。パッチが少し異なるバージョンであるかどうかは関係ありません。あなたのディストロの別のバージョンから。

ただし、これが機能する場合は、C ++コード(またはC ++ランタイムサポートを使用するコード)を動的にリンクすることはできません。

これも真実ではありません。

とは言うものの、静的にリンクすることlibstdc++.aはあなたにとって1つのオプションです。

ライブラリを(を使用して)動的にロードした場合に機能しない理由は、ライブラリdlopenを(静的に)リンクしたときに、依存するlibstdc ++シンボルがアプリケーションで必要とされなかった可能性があるため、これらのシンボルは実行可能ファイルに存在しません。これは、共有ライブラリを動的にリンクすることで解決できますlibstdc++.so(これは、共有ライブラリに依存している場合はとにかく正しいことです)。ELFシンボルの挿入は、実行可能ファイルに存在するシンボルが共有ライブラリによって使用されることを意味しますが、他のシンボルは使用されません。実行可能ファイルに存在するものはlibstdc++.so、リンク先のいずれかにあります。アプリケーションが使用しない場合dlopenは、それを気にする必要はありません。

別のオプション(および私が好むオプション)はlibstdc++.so、アプリケーションと一緒に新しいものをデプロイし、デフォルトのシステムの前にそれが見つかるようにすることです。これは、実行時に環境変数をlibstdc++.so使用して、動的リンカーに適切な場所を探すように強制することで実行できます。$LD_LIBRARY_PATH時間、またはRPATHリンク時に実行可能ファイルにを設定することによって。RPATHアプリケーションが機能するために正しく設定された環境に依存しないため、私は使用することを好みます。アプリケーションをとリンクすると'-Wl,-rpath,$ORIGIN'(シェルが拡張しようとするのを防ぐために一重引用符に注意してください$ORIGIN)、実行可能ファイルには、実行可能ファイル自体と同じディレクトリで共有ライブラリを探すようにダイナミックリンカに指示するRPATHがあります。$ORIGINあなたが新しいものを置くならlibstdc++.so実行可能ファイルと同じディレクトリにあり、実行時に検出され、問題が解決されます。(別のオプションは、実行可能ファイル/some/path/bin/と新しいlibstdc ++。soを入れて、実行可能ファイルまたは他の固定位置/some/path/lib/にリンクし'-Wl,-rpath,$ORIGIN/../lib'、RPATHをに相対的に設定することです$ORIGIN

于 2012-12-29T14:22:57.957 に答える
12

Jonathan Wakelyの優れた答えへの1つの追加、なぜdlopen()が問題になるのか:

GCC 5の新しい例外処理プール(PR64535およびPR65434を参照)により、libstdc ++に静的にリンクされているライブラリをdlopenおよびdlcloseすると、毎回(プールオブジェクトの)メモリリークが発生します。したがって、dlopenを使用する可能性がある場合は、libstdc++を静的にリンクすることは非常に悪い考えのように思われます。これは、PR 65434で言及されている良性のリークとは対照的に、実際のリークであることに注意してください。

于 2016-01-26T13:52:56.467 に答える
3

また、動的glibcに依存しないようにする必要がある場合もあります。結果の実行可能ファイルで実行lddし、動的な依存関係をメモします(libc / libm / libpthreadは通常の疑いです)。

追加の演習では、この方法論を使用して関連するC ++ 11の例を多数作成し、実際の10.04システムで結果のバイナリを実際に試します。ほとんどの場合、動的ロードで何か変なことをしない限り、プログラムが機能するかクラッシュするかがすぐにわかります。

于 2012-11-29T23:34:36.680 に答える
3

RPATHに関するJonathanWakelyの回答へのアドオン:

RPATHは、問題のRPATHが実行中のアプリケーションのRPATHである場合にのみ機能します。独自のRPATHを介して任意のライブラリに動的にリンクするライブラリがある場合、ライブラリのRPATHは、それをロードするアプリケーションのRPATHによって上書きされます。これは、アプリケーションのRPATHがライブラリのRPATHと同じであることを保証できない場合に問題になります。たとえば、依存関係が特定のディレクトリにあると予想されるが、そのディレクトリがアプリケーションのRPATHの一部ではない場合です。

たとえば、GCC4.9のlibstdc++。so.xに動的にリンクされた依存関係を持つアプリケーションApp.exeがあるとします。App.exeは、RPATHを介してこの依存関係を解決します。

App.exe (RPATH=.:./gcc4_9/libstdc++.so.x)

ここで、GCC5.5のlibstdc++。so.yに動的にリンクされた依存関係を持つ別のライブラリDependency.soがあるとします。ここでの依存関係は、ライブラリのRPATHを介して解決されます。

Dependency.so (RPATH=.:./gcc5_5/libstdc++.so.y)

App.exeがDependency.soをロードするとき、ライブラリのRPATHを追加も追加もしません。全く相談しません。考慮される唯一のRPATHは、実行中のアプリケーション、またはこの例ではApp.exeのRPATHです。つまり、ライブラリがgcc5_5 / libstdc ++。so.yにあるが、gcc4_9 / libstdc ++。so.xにはないシンボルに依存している場合、ライブラリのロードに失敗します。

私は過去にこれらの問題に遭遇したことがあるので、これは警告の言葉と同じです。RPATHは非常に便利なツールですが、その実装にはまだいくつかの落とし穴があります。

于 2019-06-19T17:24:05.743 に答える
1

ジョナサン・ウェイクリーの答えに次のように付け加えたいと思います。

-static-libstdc++Linuxで遊んでいると、で問題が発生しましdlclose()た。アプリケーション「A」が静的にリンクされており、実行時にプラグイン「P」libstdc++に動的にリンクされてロードされるとします。libstdc++それはいいです。ただし、「A」が「P」をアンロードすると、セグメンテーション違反が発生します。私の仮定では、アンロード後libstdc++.so、「A」はに関連するシンボルを使用できなくなりますlibstdc++。'A'と'P'の両方が静的にリンクされているlibstdc++場合、または'A'が動的にリンクされて'P'が静的にリンクされている場合、問題は発生しないことに注意してください。

概要:アプリケーションがに動的にリンクする可能性のあるプラグインをロード/アンロードする場合、libstdc++アプリも動的にリンクする必要があります。これは私の観察であり、コメントをお願いします。

于 2019-02-27T19:16:30.903 に答える