5

Boost.thread を内部で使用する共有ライブラリを構築しています。その結果、Boost.thread がそれに依存するため、Boost.system も使用されます。私の共有ライブラリは C インターフェイスをエクスポートするため、内部例外処理やスレッドの使用などをすべてエンド ユーザーから隠したいと考えています。いわばブラックボックスのはずです。ただし、クライアントアプリケーションとリンクすると、プログラムは正常に実行されますが、ライブラリ関数を呼び出して処理を停止するとすぐに、次のようになります。

「boost::thread_interrupted」のインスタンスをスローした後に呼び出される終了

私はこの例外をライブラリの内部でキャッチするので、なぜ実際にキャッチされないのかわかりません。エンド ユーザーのプログラムは、Boost 例外を認識したり、処理したりすることを意図したものではありません。共有ライブラリを構築するときは、Boost.thread と Boost.system の両方に静的リンクを使用するので、外の世界からそれらが見えないようにしています。私はUbuntu 12でGCC 4.7を使用しています。Windowsでは、そのような問題はありません(MSVCでもMinGwでも)。

(編集)

コメントのリクエストに従って、問題を再現する最小限の例を示すために質問を編集しています。

最初に、testlib.cpp と testlib.h のコードを示します。

testlib.cpp:

#include <boost/thread/thread.hpp>

void thread_func()
{
ながら(1)
{
ブースト::this_thread::interruption_point();
}
}

ボイド do_processing()
{
// 上記の関数を実行するスレッドを開始します。
ブースト::スレッドワーカー(thread_func);

// この例では、スレッドが適切に開始されたと想定しています。

// スレッドを中断しましょう。
worker.interrupt();

// そして、終了するのを待ちましょう。
worker.join();
}

そして今、testlib.h:

#ifndef TESTLIB_H
#TESTLIB_H を定義

void do_processing();

#endif

次のコマンドを使用して、これを共有ライブラリにビルドします。

g++ -static-libgcc -static -s -DNDEBUG -I /usr/boost_1_54_0 -L /usr/boost_1_54_0/stage/lib -Wall -shared -fPIC -o libtestlib.so testlib.cpp -lboost_thread -lboost_system -lpthread -O3

次に、次のような単純なクライアント プログラムのコードを作成します。

#include "testlib.h"
#include <cstdio>

int main()
{
do_processing();
printf("実行は正常に完了しました。\n");
0 を返します。
}

次のようにクライアントを構築します。

g++ -DNDEBUG -I /usr/boost_1_54_0 -L ./ -Wall -o クライアント client.cpp -ltestlib -O3

クライアントを実行すると、次のようになります。

'boost::thread_interrupted' のインスタンスをスローした後に呼び出された終了
中止 (コア ダンプ)

私はスレッド割り込み例外を明示的にキャッチしていませんが、Boost ドキュメントによると、Boost.thread はそれを行い、指定されたスレッドのみを終了します。thread_func 関数内から例外を明示的にキャッチしようとしましたが、違いはありませんでした。

(編集終了)

(編集2)

-fexceptions をオンにしても、問題は解決しないことに注意してください。また、例外をキャッチしてスローするコードと同じ翻訳単位で定義されている例外をスローしてキャッチしようとしましたが、改善されませんでした。要するに、すべての例外は、共有ライブラリでキャッチされていないように見えます。クライアント ファイルと testlib ファイルを 1 つのプログラムの一部としてコンパイルすると、つまり testlib を共有ライブラリにしないと、すべてが期待どおりに機能します。

(編集2の終わり)

任意のヒント?

4

3 に答える 3

0

それ自体が静的にリンクされたライブラリを含む共有ライブラリはあまり良い考えではなく、このシナリオが GNU ツールチェーンで十分にサポートされているとは思いません。

あなたの特定の問題はオプション-static-libgccに起因すると思いますが、あなたのオプションを使用して私のマシンでコンパイルできませんでした。静的に動的にリンクすることlibpthread.soも良いアイデアのように聞こえるわけではありません...メインの実行可能ファイルが独自のスレッドを作成したい場合はどうなりますか? でコンパイルされ-pthreadますか?そうであれば、スレッド関数を 2 回リンクします。そうでない場合、関数は含まれますが、プリコンパイラ マクロやスレッド セーフ ライブラリ関数は含まれません。

私のアドバイスは、ライブラリを静的にコンパイルしないことです。それは Linux のやり方ではありません。

実際には、boost のディストリビューション バージョンに依存したくない場合でも、実際には問題になることはありません。プログラムを共有 boost ライブラリに対してコンパイルし、これらすべてのファイル ( libboost_thread.so.1.54.0libboost_system.so.1.54.0およびlibtestlib.so) を同じディレクトリに展開します。次に、でプログラムを実行しますLD_LIBRARY_PATH=<path-to-so-files>。クライアントはブーストを直接使用することを意図していないため、ブースト ヘッダーは必要なく、コンパイラ コマンドでそれらをリンクする必要もありません。ブラック ボックスはまだありますが、1 つではなく 3 つの *so ファイルで形成されています。

于 2013-08-10T00:15:57.917 に答える