mal*_*lat 6 c c++ pointers language-lawyer
希望这是一个简单的C++问题(不是语言律师问题).
如何dladdr在C++中使用GNU扩展?通常会在C中写下以下内容:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
static void where_am_i() {}
int main()
{
Dl_info info;
dladdr( (void*)&where_am_i, &info );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是使用clang可以看到演员表可能无效:
$ clang --version
Debian clang version 3.6.2-3 (tags/RELEASE_362/final) (based on LLVM 3.6.2)
Target: x86_64-pc-linux-gnu
Thread model: posix
$ clang -Wpedantic -o foo foo.cpp -ldl
foo.cpp:11:11: warning: cast between pointer-to-function and pointer-to-object is an extension [-Wpedantic]
dladdr( (void*)&where_am_i, &info );
^~~~~~~~~~~~~~~~~~
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
警告对我来说似乎是合法的,那么有办法解决这个问题吗?
没有标准方法可以将函数指针可移植地转换为void*. 因此,没有可移植使用的标准方法dladdr。在 C++11 之前,此类转换的格式不正确(我没有可用的文档,但 clang 的警告表明了这一点)。然而,从 C++11 开始,有条件地支持转换:
[expr.reinterpret.cast] /8(标准草案)
有条件地支持将函数指针转换为对象指针类型,反之亦然。这种转换的含义是实现定义的,除非实现支持双向转换,将一种类型的纯右值转换为另一种类型并返回(可能使用不同的 cv 限定)将产生原始指针值。
由于您已经依赖于提供的 c 库扩展dladdr,因此您不妨依赖可将函数指针强制转换为 的语言扩展void*。在这种情况下,您可能希望通过在没有该选项的-Wpedantic情况下进行编译来要求编译器不要警告有关使用语言扩展的问题,或者使用至少有条件支持转换的标准版本。如果不支持转换,则也不支持dladdr。