¿Qué sentido tiene esto ?: * (void **) (& fptr) = dlsym (handle, “my_function”); `

El código proviene de esta página: http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html

¿Puedes ayudarme a entender esto? Toma la dirección del puntero de la función, la convierte en nulo ** y luego la desactiva. No sé por qué tiene que funcionar así.

¡Aprecio tu ayuda! Hasta ahora, el único consejo que recibí fue “leerlo de derecha a izquierda” o algo así como “leerlo en ciclos de derecha a izquierda”.

El significado del código es:

  1. Tome la dirección de fptr . El tipo de esta expresión es puntero a puntero a función (de algún tipo específico).
  2. Convierta esa expresión de puntero a “puntero a puntero a anular”.
  3. Dereferencia de ese puntero para acceder al objeto fptr como si fuera un objeto de tipo void * .
  4. Asigne el resultado del derecho al valor de l obtenido en el paso 3.

Desafortunadamente, quienquiera que escribió este ejemplo en POSIX estaba en crack, porque el paso 3 viola las reglas de aliasing del lenguaje C y, por lo tanto, invoca un comportamiento indefinido. En particular, los comstackdores del mundo real optimizarán este código de manera que rompa el uso previsto.

Lo que el autor de este ejemplo intentaba lograr era evitar lanzar el lado derecho del puntero al vacío al puntero al funcionamiento . Esto se basa en una afirmación de que el estándar de C requiere que este modelo genere una advertencia, pero he buscado exhaustivamente ese requisito y no puedo encontrarlo.

Si tal problema realmente existe (el requisito de advertencia), entonces la única forma de silenciar la advertencia sin invocar un comportamiento indefinido (como el mal ejemplo en el texto de POSIX) es hacer esto:

 void (*fptr)(); // or whatever function pointer type you want void *temp = dlsym(handle, "my_function"); memcpy(&fptr, &temp, sizeof fptr); 

La función devuelve un puntero a función. Ese código dice hey toma mi variable de puntero de función dame la dirección del mismo. Echarlo al void ** . Ahora deferencia el void ** y establezca el valor del vacío * = al puntero que recibí de la llamada.

*(void **)(&fptr) = dlsym(handle, “my_function”);

Para hacer esto más simple,

fptr es un puntero.

&fptr es la dirección de ese puntero.

estás encasillando a un pointer to a pointer to a void

y luego haga referencia y asigne el valor de retorno de la función.