std::function 来自 dlsym 导致分段错误
std::function from dlsym results in segmentation fault
我想动态地 link 共享库并将其中的函数分配给 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
main.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
不起作用。
求求你帮忙!
你最好用C++风格进行转换:
using function_ptr = double (*)(std::array<double, 1>);
function_ptr function = reinterpret_cast<function_ptr>( dlsym(handle, "function") );
但罪魁祸首是关闭共享库后无法通过std::function
包装器直接或间接调用此函数:
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?
我想动态地 link 共享库并将其中的函数分配给 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
main.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
不起作用。
求求你帮忙!
你最好用C++风格进行转换:
using function_ptr = double (*)(std::array<double, 1>);
function_ptr function = reinterpret_cast<function_ptr>( dlsym(handle, "function") );
但罪魁祸首是关闭共享库后无法通过std::function
包装器直接或间接调用此函数:
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?