在共享库中使用std :: thread导致SIGSEGV

问题描述 投票:1回答:1

我刚从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 discusswalkaround使用boost::thread而不是std::thread并链接到boost_thread库,不再崩溃。

c++ shared-libraries dynamic-linking stdthread
1个回答
3
投票

我想这个问题与动态链接有关比线程。

呼叫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_librariestest

© www.soinside.com 2019 - 2024. All rights reserved.