dladdr:指向函数的指针与指向对象的指针

时间:2016-09-15 10:02:19

标签: c++ c pointers language-lawyer

希望这是一个简单的C ++问题(不是语言律师问题)。

如何在C ++中使用GNU扩展dladdr?通常会在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;
}

然而,使用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.

警告对我来说似乎合法,所以有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

没有标准方法可以将函数指针可移植地转换为void*。因此,没有可移植地使用dladdr的标准方法。在C ++ 11之前,这种转换是不正确的(我没有提供该文档,但clang的警告暗示了这一点)。但是,从C ++ 11开始,有条件地支持转换:

[expr.reinterpret.cast] / 8(标准草案)

  

有条件地支持将函数指针转换为对象指针类型,反之亦然。这种转换的含义是实现定义的,除非实现支持两个方向的转换,将一种类型的prvalue转换为另一种类型并返回,可能具有不同的cv-qualification,将产生原始指针值。 / p>

由于您已经依赖于提供dladdr的c库扩展,因此您可能依赖于允许您将函数指针强制转换为void*的语言扩展。在这种情况下,您可能希望编译器不通过编译而不使用-Wpedantic选项来警告使用语言扩展 - 或者使用至少有条件地支持转换的标准版本。如果不支持转换,则不会dladdr