我刚从Windows进入Linux c ++编程。试图制作一个共享库libso.so,该库使用std::thread
。共享库将由其他人加载并调用导出功能。测试代码:
// so.cpp, the .so library
#include <iostream>
#include <thread>
using namespace std;
extern "C"
void run() {
cout << "run() begin" << endl;
std::thread t([] {
});
t.join();
cout << "run() end" << endl;
}
// test.cpp, the test loader
#include <iostream>
using namespace std;
#include <dlfcn.h>
int main() {
typedef void (*run_t)();
auto dll = dlopen("libso.so", RTLD_LAZY);
if(dll == 0) {
cout << "dlopen fail: " << dlerror() << endl;
return 1;
}
run_t run = (run_t) dlsym(dll, "run");
run();
}
// The CMakeLists.txt file
cmake_minimum_required(VERSION 3.0)
PROJECT (test)
Include_Directories(${PROJECT_SOURCE_DIR})
Link_Directories(${PROJECT_BINARY_DIR})
add_library(so SHARED so.cpp )
target_link_libraries(so pthread)
add_executable( test test.cpp )
target_link_libraries(test pthread dl)
它在run()
函数中崩溃,输出为:
run() begin
“./test” terminated by signal SIGSEGV (Address boundary error)
std::thread
在可执行文件中似乎工作正常,但在共享库中却无法正常工作。我想念什么?
环境:g ++ 9.3.0,cmake 3.16.3
UPDATE:
std::thread
在可执行文件中工作正常,但在共享库中崩溃。找到一些related discuss,walkaround使用boost::thread
而不是std::thread
并链接到boost_thread
库,不再崩溃。
我想这个问题与动态链接有关比线程。
呼叫dlopen("libso.so", RTLD_LAZY)
将尝试在标准位置找到图书馆。除非您设置了LD_LIBRARY_PATH
环境变量包含.
(当前目录)。找不到该库。
对于简单测试,您可以:
export LD_LIBRARY_PATH=.
启动程序,dlopen("./libso.so", RTLD_LAZY)
。如果使用空值,则使用dlopen()
或dlsym()
后指针,然后dlerror()
可以帮助显示原因失败的原因。
注意,在Windows上,当前目录和可执行文件path是动态库的标准搜索路径;在UNIX上事实并非如此,更改时可能会令人惊讶目标平台。
edit
cmake
使用-Wl,-rpath
选项对库搜索进行硬编码可执行文件中的路径,所以我上面解释的所有内容都变成了对于这个问题没有用。
假设找到了动态库,我可以复制的唯一方法崩溃是为了[pthread
中的forgettarget_link_libraries
test
。