【问题标题】:std::function from dlsym results in segmentation fault来自 dlsym 的 std::function 导致分段错误
【发布时间】:2018-05-18 16:05:59
【问题描述】:

我想动态链接一个共享库并将其中的一个函数分配给std::function。代码如下:

function.cpp:

#include <array>

#ifdef __cplusplus
extern "C" {
#endif

double function(std::array<double, 1> arg)
{
    return arg[0] * 2;
}

#ifdef __cplusplus
}
#endif

ma​​in.cpp:

#include <functional>
#include <iostream>
#include <fstream>
#include <array>
#include <functional>

#ifdef __linux__
#include <dlfcn.h>
#endif

int main()
{
void *handle;
double (*function)(std::array<double, 1>);
char *error;

handle = dlopen("/home/oleg/MyProjects/shared_library_test/libFunction.so", RTLD_LAZY);
if (!handle) 
{
    fprintf(stderr, "%s\n", dlerror());
    exit(EXIT_FAILURE);
}

dlerror();
*(void **) (&function) = dlsym(handle, "function");

if ((error = dlerror()) != NULL)
{
    fprintf(stderr, "%s\n", error);
    exit(EXIT_FAILURE);
}

std::cout << "Native function output: " << function(std::array<double, 1>{ 3.0 }) << std::endl;
dlclose(handle);

std::function<double(std::array<double, 1>)> std_function(*function);
std::cout << "std::function output: " <<  std_function(std::array<double, 1>{ 3.0 }) << std::endl;

exit(EXIT_SUCCESS);
}

构建共享库:

g++ -Wall -Wextra -g -std=c++17 -shared -o libFunction.so -fPIC function.cpp

构建主体:

g++ -Wall -Wextra -g -std=c++17 main.cpp -ldl

运行程序会得到以下输出:

Native function output: 6
Segmentation fault

所以,如您所见,我成功编译了库并将其加载到我的主程序中。但是,将函数指针分配给std::function 不起作用。

请帮忙!

【问题讨论】:

  • gdb 调试器说明了那次崩溃?
  • @BasileStarynkevitch 抱歉,不知道如何使用 gdb,我只在 IDE 中工作。顺便说一句,我会试着用它做点什么,如果它仍然是真实的,我会告诉它说什么:)
  • std_function 是什么?
  • @keith 显然是一个 std::function 实例。
  • 在C++中编码时,你需要学习如何使用gdb。如果您觉得通过某些 IDE 使用调试器更容易,那就这样做吧。我建议花几个小时来学习如何在命令行上使用gdb

标签: c++ linux dynamic-linking std-function dlsym


【解决方案1】:

你最好用 C++ 风格进行转换:

using function_ptr = double (*)(std::array<double, 1>);
function_ptr function = reinterpret_cast<function_ptr>( dlsym(handle, "function") );

但罪魁祸首是关闭共享库后,你不能直接或间接通过std::function wrapper调用这个函数:

dlclose(handle);
// function cannot be used anymore

请注意,为此使用 RAII 会更好:

std::unique_ptr<void *,int(void*)> handle( dlopen("/home/oleg/MyProjects/shared_library_test/libFunction.so", RTLD_LAZY), dlclose );

那么你不需要手动调用dlclose()

注意:在 C++ 中从main() 调用exit 是一个坏主意,请改用return,详细信息可以在这里找到Will exit() or an exception prevent an end-of-scope destructor from being called?

【讨论】:

  • 有一个类似的(虽然已删除)答案。它没有解决问题,尝试使用 std::function 时仍然出现分段错误
  • 是的,它有帮助!谢谢你:)
  • 演员阵容是红鲱鱼。虽然看起来很不可思议,但其实是一样的。段错误仅由 dlclose 引起。
  • 关于 RAII 方法的非常有用的信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多