2016-09-15 39 views
6

Umarım bu basit bir C++ sorusudur (bir dil avukatı değil).dladdr: işaretçi-işleçle işaretçi-nesne-nesne

Nasıl bir C++ GNU uzantısı dladdr kullanmak gerekiyordu? Tipik bir C aşağıdaki yazarsınız:

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

biri dökme geçersiz olabilir görebilirsiniz clang kullanarak:

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

uyarı böylece geçici bir çözüm için bir yol var, bana meşru görünüyor bu mu

+1

Hayır, bu "dl" API'sinin genel bir sınırlamasıdır. Fonksiyon işaretleyicilerini, C standardıyla çalışmayı garanti etmeyecek şekilde boşluk işaretçilerine paketler, ancak Posix, fonksiyon göstergelerini (ve "dl" fonksiyonlarının Posix'in bir parçası) tutabilmesi için boşluk göstergelerini gerektirir. –

+0

Böyle yazmak daha iyidir: void * p;/* dl ... */* reinterpret_cast (& where_am_i) = p; ' –

+0

Sadece emin olmak için: C++ kodundan bahsediyoruz, C++ 14 Tahmin ediyorum? –

cevap

2

portably void* için bir işlev işaretçisi dönüştürmek için standart bir yolu yoktur. Gibi, dladdr portably kullanmak için standart bir yol yoktur. C++ 11'den önce, böyle bir dönüşüm kötü biçimlendirilmişti (belgeyi kullanmam mümkün değil, fakat clang'ın uyarısı bunu gösteriyor). C++ Bununla birlikte, 11 için, dönüşüm koşullu desteklenir:

[expr.reinterpret.cast]/8 (standart taslak) bir amacı, işaretçi türü ya da tam tersi için bir işlev işaretçisi dönüştürme

şartlı desteklenir. Böyle bir dönüşümün anlamı, uygulama tanımlamasıdır, çünkü bir uygulama, her iki yönde de dönüşümleri destekliyorsa, bir türden bir primi, diğer tür ve geri, muhtemelen farklı cv-yeterliliğine dönüştürmek, orijinal işaretçi değerini vermelidir. Zaten dladdr sağlar c kütüphanesi uzantısı güvenerek olduğundan


, siz de size void* işlev işaretçisi döküm sağlayan dil uzatma güvenmek olabilir. Bu durumda, derleyiciden, -Wpedantic seçeneği olmadan derleme yaparak dil uzantılarını kullanma konusunda uyarmalarını istemeyebilirsiniz veya dönüşümün en azından koşullu olarak desteklendiği standart bir sürüm kullanın. Dönüşüm desteklenmiyorsa, dladdr değil.