Con referencia al siguiente código
test_linker.cpp
int main() { srand(time(0)); for (int i = 0; i < 10; ++i) { cout << rand() % 10 << endl; } return 0; }urandom.cpp
#include <iostream> using std::cout; using std::endl; #include <dlfcn.h> int rand() throw() { // get the original rand() function static auto original_rand = (decltype(&rand)) dlsym(RTLD_NEXT,"rand"); cout << "Call made to rand()" << endl; return original_rand(); }Cuando intento compilar el código con el siguiente comando
g++ -std=c++11 -Wall -Werror -Wextra -Wvla -pedantic -O3 urandom.cpp -c g++ -std=c++11 -Wall -O3 test_linker.cpp urandom.o -ldl todo funciona bien, pero cuando muevo el indicador -ldl para que esté antes de los archivos, el enlazador arroja un error que dice
urandom.cpp:(.text+0xaf): undefined reference to `dlsym'Pregunta 1 ¿Alguien podría explicar por qué sucedería esto? Por lo general, no me importa el orden de las banderas en un comando de compilación.
Pregunta 2 ¿También es incorrecto mantener el puntero de función a la función rand() original como una variable estática? No sé cómo funciona exactamente el enlace dinámico y me temo que tal vez la dirección de la función se mueva en la memoria en tiempo de ejecución. Las páginas del manual decían que la función dlsym() con el identificador RTLD_NEXT es un cálculo costoso, por lo que solo quería evaluar esto de forma perezosa una vez.
Nota: Estoy compilando esto en una distribución de Linux y el enlazador dinámico de Linux está involucrado, así que continuaré y etiquetaré esto con Linux también.
-ldl es una designación de biblioteca para el enlazador. Le dice al enlazador que busque y vincule un archivo llamado libdl.so (o, a veces libdl.a ). Tiene el mismo efecto que colocar una ruta completa a la biblioteca en cuestión en la misma posición de la línea de comando.
El orden de la biblioteca y el objeto en la línea de comando es importante. Normalmente, si la biblioteca A llama a la biblioteca B, B debe colocarse después de A en la línea de comando. Todas las bibliotecas normalmente deberían ir tras todos los archivos de objetos. Esto se cubre extensamente en varias preguntas y respuestas de SO como esta .
En cuanto a la segunda pregunta, no, la dirección de una función no cambia en tiempo de ejecución a menos que dlopen una biblioteca compartida, luego la descargue y luego la dlopen nuevamente. En su caso, dado que no dlopen la biblioteca, es seguro mantener la dirección de la función en una variable estática. Por supuesto, si ejecuta varios subprocesos, debe garantizar la seguridad de los subprocesos de alguna manera (mutex, o use almacenamiento local de subprocesos).
Comience con su segunda pregunta, la vinculación dinámica funciona durante el tiempo de ejecución de cualquier manera en C/C++, llamamos vinculación posterior con esta -> operación. Por supuesto, cuando invoque un enlace posterior declarado como una interfaz o instancia de clase, debe apuntar al objeto especificado y la ubicación de memoria para ese objeto.
La primera pregunta es más, creo, específica del compilador. Supongo que no está compilando en Visual Studio (no en el sistema operativo Windows), si tengo razón, debe pedirle al proveedor del compilador que configure las propiedades de depuración. :)