我目前正在尝试在一个共享库中使用C++ 11多线程,该库被加载到Linux上的主程序(用C语言编写)中.这是大型模拟程序的一部分,我无法改变有关库加载或更改主程序的任何内容.
主程序是用gcc 4.1.2编译的,我没有它的源代码(我不能用gcc 4.8.2重新编译它).
共享库使用gcc 4.8.2编译,以便使用C++ 11多线程.我正在传递编译器命令
-pthread -lpthread -std=c++11
正如在Linux下的GCC中使用std :: thread的正确链接选项中所解释的那样?
使用此配置(" -pthread -std=c++11
"和gcc 4.8)编译独立测试程序在我的系统上正常工作.但是当我启动加载共享库的程序时,我得到一个异常:
Caught std::exception!
Exception Message: Enable multithreading to use std::thread: Operation not permitted
Terminating...
使用-pthread
和-lpthread
(编辑:也只是-pthread
没有-lpthread
)编译参数不起作用.编译器参数是(我正在使用cook构建系统):
-pthread -std=c++11 -fmessage-length=0 -fPIC -Wchar-subscripts ...(lots of -W* here)
... -Wunused-variable -m64 -D__64BIT__ -pthread -lpthread
和链接器参数(由于构建系统而产生的重复参数):
-pthread -lpthread -std=c++11 -pthread -lpthread -std=c++11 -shared -fPIC -Wl,-Bsymbolic -Wl,--allow-shlib-undefined -pthread -lpthread
在我的库上调用ldd会给出以下输出
$ ldd calc3/build/amd64_linux26_RH5/library.so
linux-vdso.so.1 => (0x00007fff4d1fd000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002ae6ec124000)
libstdc++.so.6 => /afs/bb/data/d6833/util/gcc_482/lib64/libstdc++.so.6 (0x00002ae6ec340000)
libm.so.6 => /lib64/libm.so.6 (0x00002ae6ec655000)
libgcc_s.so.1 => /afs/bb/data/d6833/util/gcc_482/lib64/libgcc_s.so.1 (0x00002ae6ec8d8000)
libc.so.6 => /lib64/libc.so.6 (0x00002ae6ecaef000)
/lib64/ld-linux-x86-64.so.2 (0x00000032cb400000)
并在主程序上
$ ldd .../bin-64/main_program
linux-vdso.so.1 => (0x00007fff64595000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000032cc000000)
libz.so.1 => /usr/lib64/libz.so.1 (0x00000032cc800000)
libc.so.6 => /lib64/libc.so.6 (0x00000032cb800000)
/lib64/ld-linux-x86-64.so.2 (0x00000032cb400000)
pthread库链接到我的共享库,但不链接到主程序.这个答案表明你必须将pthreads链接到主程序,但是这个答案的第二个评论(由@R ..)表示没有必要(这听起来像逻辑上).
不幸的是,除了我的库使用另一个C++库作为API之外,我对整个系统的加载机制一无所知.
请注意,其他C++ 11功能可以工作(和libstdc ++.所以在我的库的依赖项中),但C++ 11多线程不是(尽管libpthread.so也在我的库的依赖项中).
使用程序本身包含的库中的线程类是可行的(这个线程类似乎也使用pthreads).
我也试过使用-fabi-version=0
或-fabi-version=2
因为主程序是用我的库用gcc 4.1.2编译的,但它没有改变任何东西.
有什么我忽略的或者我可以使用编译器选项来使它工作吗?或者它似乎是我的程序环境的问题?欢迎任何想法.
编辑:
我尝试使用-Wl,-no-as-needed
(如评论中所建议的那样),但遗憾的是它没有改变任何东西.
使用clang 3.5而不是gcc 4.8也不起作用.
只要我对主应用程序和共享库使用gcc 4.8或clang 3.5,创建一个加载共享库的小型测试应用程序(如下面@chill的答案)就可以工作(即使没有编译器标志).当使用gcc 4.1作为主程序时,主程序甚至无法加载库(它在我的'真实'应用程序中工作).我认为编译器的不同ABI可能存在问题.
直接使用pthreads pthread.h
似乎工作(虽然程序目前终止pthread_join
没有错误消息,但我仍然在那里测试...)
编辑2:
运行'测试程序' LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
(因为gcc 4.8库路径也需要在那里,感谢@MvG)确实运行程序但是再次崩溃,但Enable multithreading to use std::thread: Operation not permitted
异常.
我检查了所有其他加载的库(找到strace ./main_program 2>&1 | grep '^open(".*\.so"'
[见这里 ])并用它们全部检查ldd
.它们都依赖于相同的库(具有相同的路径).ldd
输出(在所有这些上):
linux-vdso.so.1 => (0x00007fff4d3fd000)
libstdc++.so.6 => /afs/bb/data/d6833/util/gcc_482/lib64/libstdc++.so.6 (0x00002ade28774000)
libm.so.6 => /lib64/libm.so.6 (0x00002ade28ab0000)
libgcc_s.so.1 => /afs/bb/data/d6833/util/gcc_482/lib64/libgcc_s.so.1 (0x00002ade28d33000)
libc.so.6 => /lib64/libc.so.6 (0x00002ade28f49000)
/lib64/ld-linux-x86-64.so.2 (0x00000032ea200000)
(他们都不依赖于libpthread.so.0,除了我的库和另外一个(但它是相同的/lib64/libpthread.so.0
))
有些库确实有更多的依赖项(它们似乎与线程无关)但似乎没有任何"冲突"依赖项(在这些库中没有依赖于同一个库的不同版本/路径).