2011-04-05 11 views
39

¿En qué situación es posible que GCC no arroje un mensaje de error de enlace de "referencia no definida" cuando intenta llamar a funciones inventadas?¿Puede GCC no quejarse de referencias indefinidas?

Por ejemplo, una situación en la que se compila el código C y vinculado por GCC:

void function() 
{ 
    made_up_function_name(); 
    return; 
} 

... a pesar de que made_up_function_name no está presente en cualquier parte en el código (no encabezados, archivos de origen, declaraciones, ni ninguna biblioteca de terceros).

¿Puede ese tipo de código ser aceptado y compilado por GCC bajo ciertas condiciones, sin tocar el código real? Si es así, ¿cuál?

Gracias.

EDITAR: ninguna declaración anterior o menciones a made_up_function_name están presentes en ningún otro lado. Lo que significa que un grep -R de todo el sistema de archivos será y solo mostrará esa única línea de código exacta.

+0

Puede (siempre que compile C, no C++). ¿Qué estás tratando de lograr sin embargo? –

+0

No estoy tratando de lograr nada, ya está sucediendo y me gustaría saber por qué es posible. El made_up_function_name está realmente presente en el binario final, vinculado, si uso "-g" y edito el archivo con un editor de texto. – STenyaK

+1

En cuanto a por qué, consulte: http://stackoverflow.com/questions/4914589/c-prototype-functions/4914683, http://stackoverflow.com/questions/4800102/not-including-stdlib-h-does-not -produce-any-compiler-error/4800138 # 4800138, y probablemente bastantes más. –

Respuesta

68

Sí, es posible evitar el reporte de referencias indefinidas - usando --unresolved-symbols opción del enlazador.

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files 

Desde man ld

--unresolved-símbolos = método

determinar cómo manejar símbolos sin resolver. Hay cuatro valores posibles para método:

 ignore-all 
      Do not report any unresolved symbols. 

     report-all 
      Report all unresolved symbols. This is the default. 

     ignore-in-object-files 
      Report unresolved symbols that are contained in shared 
      libraries, but ignore them if they come from regular object 
      files. 

     ignore-in-shared-libs 
      Report unresolved symbols that come from regular object 
      files, but ignore them if they come from shared libraries. This 
      can be useful when creating a dynamic binary and it is known 
      that all the shared libraries that it should be referencing 
      are included on the linker's command line. 

El comportamiento de las bibliotecas compartidas en su propio también puede ser controlado por el - [no-] opción allow-shlib-indefinido.

Normalmente, el vinculador generará un mensaje de error por cada símbolo sin resolver informado pero la opción --warn-unresolved-symbols puede cambiar esto a una advertencia.

3

Si declara el prototipo de la función antes de usarla, debe compilarla. De todos modos, el error durante la vinculación se mantendrá.

void made_up_function_name(); 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 
+0

Pregunta editada para reflejar esto: no hay ninguna otra mención a la función compensada, que no sea la línea de llamada que se muestra en el ejemplo. – STenyaK

1

Si function() Nunca se llama, puede que no se incluye en el ejecutable, y la función llamada de ella no se busca, ya sea para.

+0

para que pueda compilarse incluso sin declarar el prototipo y luego vincularse también? Creo que al menos el prototipo debería declararse, de lo contrario generaría un error de análisis, ¿verdad? – Heisenbug

+0

@ 0verbose - Depende del estándar C que use. Originalmente, los prototipos no eran necesarios. Y más adelante solo si tiene tipos de parámetros distintos de int. –

0

Y luego está esta maldad con el indicador -D pasado a GCC.

$cat undefined.c 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 


int main(){ 
} 

$gcc undefined.c -Dmade_up_function_name=atexit 
$ 

Imagínese en busca de la definición de made_up_function_name- que aparece en ninguna parte todavía "hace cosas" en el código. No puedo pensar en una buena razón para hacer esto exactamente en el código.

El distintivo -D es una poderosa herramienta para cambiar el código en tiempo de compilación.

+0

El indicador '-D' cambia el código en * compile * time. Luego hay cosas como '-Wl, - wrap', que hace eso en el momento del enlace. –

+0

Y si uno combina '-D' con la fusión del token del preprocesador, entonces el texto' made_up_function_name' no necesita aparecer como tal en ningún archivo MAKE o script de compilación tampoco. –

2

TL; DR Se puede no se quejan, pero no hacer quieren eso. Su código se bloqueará si fuerza al vinculador a ignorar el problema. Sería contraproducente.

Su código se basa en la antigua C (pre-C99) permitiendo que las funciones se declaren implícitamente en su punto de uso. Su código es semánticamente equivalente al siguiente código:

void function() 
{ 
    int made_up_function_name(...); // The implicit declaration 

    made_up_function_name(); // Call the function 
    return; 
} 

El enlazador se queja con razón que el fichero objeto que contiene el function() compilado refiere a un símbolo que no se encuentra en ninguna otra. Debe solucionarlo por proporcionando la implementación para made_up_function_name()o eliminando la llamada sin sentido. Eso es todo lo que hay. Sin linker-violín involucrado.

0

El algoritmo "estándar" según el cual funcionan los enlazadores POSIX deja abierta la posibilidad de que el código se compile y enlace sin ningún error. Consulte aquí para más detalles: https://stackoverflow.com/a/11894098/187690

el fin de explotar esa posibilidad el fichero objeto que contiene su function (vamos a llamarlo f.o), deberían entrar en una biblioteca. Esa biblioteca debe mencionarse en la línea de comando del compilador (y/o del enlazador), pero en ese momento ningún otro archivo de objeto (mencionado anteriormente en la línea de comando) debería haber llamado a function o cualquier otra función presente en f.o. En tales circunstancias, el vinculador no verá ninguna razón para recuperar f.o de la biblioteca. Linker ignorará por completo f.o, ignorará por completo function y, por lo tanto, permanecerá completamente ajeno a la llamada al made_up_function_name. El código se compilará aunque made_up_function_name no esté definido en ninguna parte.

1

Cuando compila con el indicador del vinculador -r o --relocatable, tampoco producirá ningún mensaje de error de enlace de "referencia no definida".

Esto se debe a que -r vinculará diferentes objetos en un nuevo archivo de objetos para vincularlos en una etapa posterior.

Cuestiones relacionadas