Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

296
Vistas
Casting cuando se usa dlsym()

Estoy usando dlsym() en C y tengo una pregunta sobre si el valor de retorno de dlsym() debe emitirse explícitamente o si se convierte implícitamente correctamente. Aquí está la función:

 double (*(compile)(void))(double x, double y) { if (system("scan-build clang -fPIC -shared -g -Wall -Werror -pedantic " "-std=c11 -O0 -lm foo.c -o foo.so") != 0) { exit(EXIT_FAILURE); } void *handle; handle = dlopen("./foo.so", RTLD_LAZY); if (!handle) { printf("Failed to load foo.so: %s\n", dlerror()); exit(EXIT_FAILURE); } foo f; f = (foo)dlsym(handle, "foo"); if (!f) { printf("Failed to find symbol foo in foo.so: %s\n", dlerror()); exit(EXIT_FAILURE); } return f; }

La función compile() no toma un valor y devuelve un puntero a una función que toma dos double como entrada y que devuelve un doble. Luego configuro una llamada al sistema que compila un objeto compartido foo.so Luego abro foo.so con dlopen() . Luego dlsym() encuentra foo en foo.so y devuelve un objeto de tipo foo que definí en un encabezado como:

 typedef double (*foo)(double, double);

¿Tengo que lanzar dlsym() ?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

El estándar C está escrito para asumir que los punteros a diferentes tipos de objetos, y especialmente los punteros a funciones en oposición a los tipos de objetos, pueden tener diferentes representaciones. Es por eso que, en general, no desea entremezclar punteros, o si lo hace, un compilador moderno le advertirá, y si desea silenciar las advertencias, generalmente usa un molde explícito.

dlsym , por otro lado, por su propia existencia asume que todos los punteros son prácticamente iguales, porque se supone que puede devolverle cualquier puntero a cualquier tipo de datos (objeto o función) en su archivo de objeto.

En otras palabras, el código que usa dlsym es inherentemente no portátil, en el sentido de que no es ampliamente portátil, en el sentido de que es portátil "solo" para aquellas máquinas donde todos los punteros son interconvertibles de forma segura. (Que, por supuesto, es prácticamente todas las máquinas populares en la actualidad).

Entonces, sí, deberá emitir los punteros para silenciar las advertencias y, al hacerlo, puede hacer que su código sea menos portátil para las máquinas donde todos los punteros no son iguales (y donde las advertencias, si no se silencian, se verían correctamente). informarle que su código no funcionará), pero dlsym nunca funcionará (ni siquiera existirá en su forma actual) en esas máquinas de todos modos.

(Y si gcc -pedantic le advierte incluso sobre una conversión explícita de void * a un tipo de puntero de función, no hay mucho que pueda hacer excepto cambiar a una versión diferente de gcc o, por supuesto, no usar -pedantic ).


Anexo: mi respuesta hizo que pareciera que la conversión entre punteros a diferentes tipos de datos podría ser un problema, pero eso generalmente no es un problema. Type void * está bien definido para ser el puntero de datos genérico: es lo que devuelve malloc , y está definido para ser silenciosamente convertible a cualquier tipo de puntero de objeto, es decir, se supone que ni siquiera necesita un molde. Así que es casi una buena elección para el tipo de devolución de dlsym , excepto por el pequeño problema de los punteros de función. malloc nunca tiene este problema (casi nunca intentaría llevar un puntero a una función), mientras que dlsym siempre tiene este problema (los símbolos a los que generalmente intenta acceder en archivos de objetos cargados dinámicamente son código al menos tan a menudo como son datos). Pero los punteros de función son a lo que no se garantiza que void * se convierta, por lo que es muy probable que reciba advertencias, por lo que necesita los moldes, y es posible que reciba advertencias -pedantic incluso con los moldes.

over 4 years ago · Santiago Trujillo Denunciar

0

dlsym() devuelve un valor void* . Este valor de puntero puede referirse a un objeto o a una función.

Si apunta a un objeto, entonces no es necesario convertir, ya que C define una conversión implícita de void* a cualquier tipo de puntero a objeto:

 int *ptr = dlsym(handle, "name");

Si apunta a una función (que probablemente sea mucho más común), no hay una conversión implícita de void* a ningún tipo de puntero a función, por lo que es necesario convertir.

En C estándar, no hay garantía de que un valor void* pueda convertirse significativamente en un puntero de función. POSIX, que define dlsym() , garantiza implícitamente que el valor void* devuelto por dlsym() se puede convertir significativamente en un tipo de puntero a función, siempre que el objetivo sea del tipo correcto para la función correspondiente.

Suponiendo que estamos tratando con una función nula sin parámetros:

 typedef void (*func_ptr_t)(void); func_ptr_t fptr = (func_ptr_t)dlsym(handle, "name");

Da la casualidad de que gcc (con -pedantic ) advierte sobre esto:

 warning: ISO C forbids conversion of object pointer to function pointer type

Esta advertencia no es estrictamente correcta. ISO C en realidad no prohíbe convertir un puntero de objeto en un tipo de puntero de función. El estándar enumera varias restricciones que un operador de conversión no puede violar; convertir void* en un tipo de puntero de función no es uno de ellos. El estándar C no define el comportamiento de dicha conversión, pero dado que POSIX lo hace en este caso particular, eso no es un problema.

Un comentario sobre la respuesta de Steve Summit sugiere que esto:

 *(void **) (&f) = dlsym(handle, "foo");

silenciará la advertencia de gcc. Lo hará, pero hace suposiciones que no están garantizadas ni por C ni por POSIX. POSIX garantiza que el resultado de dlsym se puede convertir en un puntero de función; no garantiza que tenga la misma representación o alineación. Es probable que funcione, pero no lo recomiendo.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda