2016-09-15 4 views
6

Hoffentlich ist dies eher eine einfache C++ - Frage (nicht eine Sprache-Anwalt).dladdr: pointer-to-function vs pointer-to-object

Wie soll man die GNU-Erweiterung dladdr in C++ verwenden? Normalerweise würde man die folgenden in C schreiben:

#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; 
} 

jedoch Klirren verwendet, kann man die Besetzung sehen ungültig sein kann:

$ 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. 

Die Warnung erscheint mir legitim, so ist es eine Möglichkeit, um zu arbeiten Das ?

+1

Nein, das ist eine allgemeine Einschränkung der "dl" API. Es verpackt Funktionszeiger in void-Zeiger in einer Weise, die nicht vom C-Standard garantiert wird, aber Posix benötigt void-Zeiger, um Funktionszeiger halten zu können (und die "dl" -Funktionen sind Teil von Posix). –

+0

Besser, es so zu schreiben: 'void * p;/* dl ... */* reinterpret_cast (& where_am_i) = p; ' –

+0

Nur um sicher zu gehen: Wir reden hier über C++ code, C++ 14 ich würde raten? –

Antwort

2

Es gibt keine standardmäßige Möglichkeit, einen Funktionszeiger portabel in void* umzuwandeln. Daher gibt es keinen Standardweg, um dladdr portabel zu verwenden. Vor C++ 11 war eine solche Umwandlung schlecht gestaltet (ich habe das Dokument nicht verfügbar, aber die Warnung durch Klopfen schlägt es vor). Da C++ 11 jedoch ist die Umwandlung bedingt unterstützt:

[expr.reinterpret.cast]/8 (Normentwurf)

einen Funktionszeiger auf einen Objektzeiger-Typ oder umgekehrt ist Converting bedingt unterstützt. Die Bedeutung einer solchen Konvertierung ist implementierungsdefiniert, mit der Ausnahme, dass, wenn eine Implementierung Konvertierungen in beide Richtungen unterstützt, die Konvertierung eines prvalue eines Typs in den anderen Typ und zurück, möglicherweise mit unterschiedlicher cv-Qualifikation, den ursprünglichen Zeigerwert ergibt.


Da Sie bereits auf der c Bibliothekserweiterung verlassen, die dladdr bietet, dann kann man auch auf der Spracherweiterung verlassen, die Sie void* werfen Funktionszeiger können. In diesem Fall sollten Sie den Compiler bitten, vor der Verwendung von Spracherweiterungen durch Kompilieren ohne die Option -Wpedantic nicht zu warnen - oder eine Standardversion zu verwenden, in der die Konvertierung zumindest bedingt unterstützt wird. Wenn die Konvertierung nicht unterstützt wird, dann ist dies nicht dladdr.

Verwandte Themen