Ara*_*dur 9 c++ shared-libraries shared-ptr undefined-behavior c++11
dlopen()是一个C函数,用于在运行时动态加载共享库.因此,如果您不熟悉,该模式是:
dlopen("libpath", flag)到void *handle图书馆dlsym(handle, "object_name")得到void *object你想要的东西objectdlclose (handle)卸载库.在C++中,这是所谓的别名构造函数的完美用例std::shared_ptr.模式变为:
std::shared_ptr<void> handlefrom dlopen("libpath", flag)将在调用dlclose()析构函数时调用std::shared_ptr<void> objectfrom handle和dlsym(handle, "object_name")object任何我们想要的地方,完全忘记handle; 当object调用析构函数时,无论何时发生,dlclose()都会自动调用绚丽的图案,效果很好.但是有一个小问题.上面的图案需要从铸void*到whatever_type_object_is*.如果"object_name"引用一个函数(考虑到用例,它大部分时间都是这样),这是未定义的行为.
在C中,有一个黑客来解决这个问题.从dlopen手册页:
// ...
void *handle;
double (*cosine)(double);
// ...
handle = dlopen("libm.so", RTLD_LAZY);
// ...
/* Writing: cosine = double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
*(void **) (&cosine) = dlsym(handle, "cos");
// ...
Run Code Online (Sandbox Code Playgroud)
这显然在C中工作正常.但有一个简单的方法来做到这一点std::shared_ptr?
上面的模式需要从 void* 到whatever_type_object_is* 的转换。如果“object_name”引用一个函数(考虑到用例,大多数情况下都是这样),这是未定义的行为。
嗯,这并不完全正确,至少在 C++ 中它只是有条件支持的。
5.2.10.8说:
有条件地支持将函数指针转换为对象指针类型,反之亦然。这种转换的含义是实现定义的,但如果实现支持双向转换,则将一种类型的纯右值转换为另一种类型并返回(可能使用不同的 cv 限定)将产生原始指针值。
因此,假设dlsym内部所做的是将函数指针强制转换为 a void*,我相信如果将其强制转换回函数指针就可以了。