我正在构建一个内部使用Boost.thread的共享库。因此,Boost.system也被使用,因为Boost.thread依赖于此。我的共享库导出了一个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() { while(1) { boost::this_thread::interruption_point(); } } void do_processing() { // Start a thread that will execute the function above. boost::thread worker(thread_func); // We assume the thread started properly for the purposes of this example. // Now let's interrupt the thread. worker.interrupt(); // And now let's wait for it to finish. worker.join(); }
现在testlib.h:
#ifndef TESTLIB_H #define 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("Execution completed properly.\n"); return 0; }
我按如下方式构建客户端:
g ++ -DNDEBUG -I / usr / boost_1_54_0 -L ./-Wall -o client client.cpp -ltestlib -O3
当我运行客户端时,我得到:
在抛出'boost :: thread_interrupted'实例后终止调用 中止(核心倾销)
我没有明确地捕获线程中断异常,但根据Boost文档,Boost.thread会这样做并仅终止给定的线程。我尝试从thread_func函数中明确捕获异常,但这没有任何区别。
(编辑结束)
(编辑2)
值得注意的是,即使启用了-fexceptions,问题仍然存在。此外,我试图抛出并捕获一个异常,该异常在与捕获和抛出它的代码相同的转换单元中定义,没有任何改进。简而言之,即使我确实有捕获它们的处理程序,所有异常似乎在共享库中仍未被捕获。当我将客户端文件和testlib文件编译为单个程序的一部分时,也就是说不将testlib放入共享库中,一切都按预期工作。
(编辑结束2)
任何提示?
答案 0 :(得分:1)
我终于明白了。如果指定了-shared,则不应指定-static标志。我的信念是,它只是告诉链接器更喜欢它链接的库的静态版本,而是使生成的动态库不适合动态链接,这有点讽刺。但它确实如此。删除-static解决了我所有的问题,我能够在动态库中静态链接Boost,完全处理异常。
答案 1 :(得分:0)
答案 2 :(得分:0)
一个共享库本身包含静态链接库并不是一个好主意,我认为这种情况在GNU工具链中得不到很好的支持。
我认为您的特定问题来自选项-static-libgcc
,但我无法使用您的选项在我的机器中编译它。并非静态地将libpthread.so
声音与-pthread
声音联系起来也不是......如果主要可执行文件想要创建自己的线程会发生什么?它会用libboost_thread.so.1.54.0
编译吗?如果是,则将链接两次线程函数;如果不是,它将具有函数,但不具有预编译器宏和线程安全库函数。
我的建议是不要静态编译你的库,这不是Linux方式。
实际上,这不应该是一个真正的问题,即使您不想依赖boost的分发版本:针对共享的boost库编译您的程序并部署所有这些文件(libboost_system.so.1.54.0
,{{ 1}}和libtestlib.so
)到同一目录。然后使用LD_LIBRARY_PATH=<path-to-so-files>
运行您的程序。由于客户端不打算直接使用boost,因此它不需要boost头,也不需要在编译器命令中链接它们。你仍然有你的黑匣子,但现在它由3 * so文件组成,而不仅仅是1。