Parece que la variable global no inicializada se trata como un símbolo débil en Gcc. Cuál es la razón detrás de esto?¿Por qué la variable global no inicializada es un símbolo débil?
Respuesta
gcc, en el modo C:
globales sin inicializar que no se declaren extern
son tratados como símbolos "comunes", no símbolos débiles.
Los símbolos comunes se fusionan en el tiempo de enlace para que todos se refieran al mismo almacenamiento; si más de un objeto intenta inicializar dicho símbolo, obtendrá un error de tiempo de enlace. (Si no se inicializan explícitamente en cualquier lugar, que serán colocados en el BSS, es decir, inicializado a 0.)
gcc, en C++ modo:
No es lo mismo - que no hace el cosa de símbolos comunes Los valores globales "no inicializados" que no están declarados extern
se inicializan implícitamente a un valor predeterminado (0 para tipos simples o constructor predeterminado).
En cualquier caso, un símbolo débil permite que un símbolo inicializado a ser anulado por un símbolo no débil inicializado del mismo nombre en tiempo de enlace.
Para ilustrar (concentrándose en el caso C aquí), voy a utilizar 4 variantes de un programa principal, que son todos iguales excepto por la forma en que se declara global
:
main_init.c:
#include <stdio.h> int global = 999; int main(void) { printf("%d\n", global); return 0; }
main_uninit.c, whic h omite la inicialización:
#include <stdio.h> int global; int main(void) { printf("%d\n", global); return 0; }
main_uninit_extern.c, que añade el
extern
palabra clave:#include <stdio.h> extern int global; int main(void) { printf("%d\n", global); return 0; }
main_weak_init.c, que inicializa
global
y declara que es un símbolo débil:#include <stdio.h> int global __attribute__((weak)) = 999; int main(void) { printf("%d\n", global); return 0; }
y another_def.c que inicializa el mismo global:
int global = 1234;
Usando main_uninit.c
por sí solo da 0:
$ gcc -o test main_uninit.c && ./test
0
pero cuando another_def.c
se incluye también, global
se inicializa de forma explícita y obtenemos el resultado esperado:
$ gcc -o test main_uninit.c another_def.c && ./test
1234
(Nota que este caso falla en su lugar si está usando C++.)
Si tratamos con tanto main_init.c
y another.def.c
lugar, tenemos 2 inicializaciones de global
, que no funcionarán:
$ gcc -o test main_init.c another_def.c && ./test
/tmp/cc5DQeaz.o:(.data+0x0): multiple definition of `global'
/tmp/ccgyz6rL.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
main_uninit_extern.c
por sí solo no va a funcionar en absoluto - la palabra clave extern
hace que el símbolo sea una referencia externa ordinaria en lugar de un símbolo común, por lo que el enlazador se queja:
$ gcc -o test main_uninit_extern.c && ./test
/tmp/ccqdYUIr.o: In function `main':
main_uninit_extern.c:(.text+0x12): undefined reference to `global'
collect2: ld returned 1 exit status
funciona bien una vez que la inicialización de another_def.c
i s incluyó:
$ gcc -o test main_uninit_extern.c another_def.c && ./test
1234
Usando main_init_weak.c
por sí solo da el valor que inicializa el símbolo débil a (999), ya que no hay nada que anularlo:
$ gcc -o test main_init_weak.c && ./test
999
Pero tirando en el otra definición de another_def.c
funciona en este caso, porque la definición fuerte allí prevalece sobre la definición débil en main_init_weak.c
:
Buena respuesta, gracias. ¿Puedo preguntar si se aplica a C++? –
Gran explicación con ejemplos. ¿Podrías también incluir qué tan débil interactúa con las funciones? – Tomek
@Maciej - ¡buen punto, olvidé que esto fue etiquetado con ambos al escribir mi respuesta originalmente! No, no es lo mismo para C++, así que actualicé mi respuesta en consecuencia. –
¿Es esto lo que quiso decir?
weak.c
#include <stdio.h>
int weak; /* global, weak, zero */
int main(void) {
printf("weak value is %d.\n", weak);
return 0;
}
strong.c
int weak = 42; /* global, strong, 42 */
ejecución de ejemplo
$ gcc weak.c $ ./a.out weak value is 0. $ gcc weak.c strong.c $ ./a.out weak value is 42.
El Esta es una extensión común, una que usa gcc (gracias a Andrey).int weak;
en weak.c es una declaración, no una definición. O puede decir que es una definición tentativa. La definición real está en strong.c
cuando ese archivo objeto está vinculado en el programa final o en weak.c
en caso contrario.
No es cierto. 'int weak' en' weak.c' es una definición.Una tentativa, pero definición sin embargo. El programa anterior * infringe * las reglas del lenguaje, pero se admite como una extensión no estándar. – AnT
Cualquier definición múltiple de un símbolo global es un comportamiento indefinido, por lo que gcc (o más bien el enlazador binutils de GNU) puede hacer lo que quiera. En la práctica, sigue el comportamiento tradicional para evitar romper el código que se basa en este comportamiento.
¿Quiere decir definición ** múltiple **? – pmg
Sí, arreglándolo. –
La pregunta se basa en una premisa incorrecta. Las variables globales no inicializadas no son símbolos débiles.
Aparentemente, la pregunta se refiere a la capacidad de definir el mismo objeto no inicializado con vinculación externa en varias unidades de traducción. Formalmente, no está permitido; es un error tanto en C como en C++.Sin embargo, al menos en C es reconocido por la norma C99 como "extensión común" de la lengua, implementado en muchos compiladores de la vida real
J.5 extensiones comunes
J.5.11 múltiple externa definiciones
puede haber más de un definición externa para el identificador de un objeto , con o sin la explícita uso de la palabra clave extern; si las definiciones no coinciden, o se inicializa más de un , el comportamiento es indefinido (6.9.2).
Tenga en cuenta que, contrariamente a la creencia popular, el lenguaje C prohíbe explícitamente la introducción de múltiples definiciones de entidades con enlaces externos en el programa, al igual que hace C++.
6,9 definiciones externas
una definición externa es un declaración externa que es también una definición de una función (que no sea definiciones en línea) o un objeto. Si un identificador declarado con enlace externo se utiliza en una expresión (distinta de como parte del operando de un operador sizeof cuyo resultado es una constante de número entero), en alguna parte de todo el programa habrá exactamente uno definición externa para el identificador ; de lo contrario, debe haber no más de un.
Sin embargo, la extensión que permite esto ha sido bastante popular con muchos compiladores de C, de los cuales GCC resulta ser uno.
La función del enlazador de soporte es necesaria para implementar los bloques comunes de FORTRAN. Notará que GCC incluye un compilador FORTRAN en la colección. Dado que las bibliotecas de soporte se implementan en C, no es sorprendente que haya una pequeña cantidad de fugas inofensivas desde el enlazador. – RBerteig
¿Puedes dar un ejemplo de definición externa y declaración externa? – Thomson
No es solo FORTRAN, las funciones en línea de C++ y las plantillas implícitamente instanciadas también son débiles. – MSalters
- 1. ¿Por qué javac se queja de la variable no inicializada?
- 2. ¿por qué el bloque catch da un error con la variable no inicializada en Java
- 3. ¿Por qué no puedo establecer una variable global en Python?
- 4. variable no inicializada de Java con curiosidad por fin
- 5. Variable global en Rails
- 6. Apple Mach-O Linker Advertencia de acceso directo en ... al símbolo débil global
- 7. ¿Qué es un método global?
- 8. Variable global "Aplicación" no reconocida
- 9. Función No Cambio Global Variable
- 10. ¿Por qué dice Perl El símbolo global "SÍMBOLO" requiere un nombre de paquete explícito en la línea X de PROGRAM.pl?
- 11. variable global como parámetro por defecto
- 12. ¿Por qué no puedo crear una matriz con el tamaño determinado por una variable global?
- 13. ¿Qué es una "referencia de marco débil"?
- 14. En Python, ¿por qué la lista [] es automáticamente global?
- 15. Variable global que no tiene alcance mundial
- 16. ¿Por qué global es nulo en la función?
- 17. Exportar un símbolo global desde una DLL de Delphi
- 18. Python locura variable global
- 19. Variable global estática utilizada por la función miembro en línea
- 20. No se puede acceder a la función variable global
- 21. ¿Cuál es la mejor manera de declarar una variable global?
- 22. Variable global "contar" ambigua
- 23. aplicación Variable global
- 24. La variable global de Android no funciona en el Servicio
- 25. ¿Por qué 'esto' no es volátil?
- 26. ¿Qué es la resolución de símbolo?
- 27. OCaml variable global vacía
- 28. ¿Qué es el símbolo "___emutls_get_address"?
- 29. ¿Qué es 'Referencia global JNI'
- 30. C tenedor frente a la variable global
muestra del código, por favor – pmg
¿Cómo llegar a esa conclusión, qué intentó, cuáles son los hechos? –
C o C++? Hay una gran diferencia. –