c linker elf

c - readelf



.bss vs COMMON: que va donde? (4)

Las variables estáticas terminan en la sección .bss. Las variables globales no inicializadas (no estáticas) van en la sección .common.

static a; //bss int c; //.common main(){ }

De mi libro:

.bss:

Variables C globales no inicializadas

COMÚN:

Objetos de datos no capitalizados que aún no están asignados

Tengo que decir que no veo una clara distinción. Ni siquiera entiendo lo que es un objeto de datos no asignado, no asignado, ... parece que nada. He utilizado la herramienta de readelf de GNU para intentar ver un código C simple, pero no puedo encontrar un solo símbolo COMÚN. He leído cosas como el tipo COMÚN de FORTRAN es un ejemplo de un símbolo COMÚN, pero no sé FORTRAN

¿Puede alguien posiblemente distinguir los dos por mí? Si es posible, con suerte con un ejemplo de C? Apreciado enormemente.

Edición : desde this post, la variable c aquí:

int c; int main() {} ...

debe ser común. Pero usar objdump -t me muestra que c está en .bss ...

confuso


Los comunes solo aparecen antes de la etapa de enlace. Los valores comunes son lo que luego se incluye en el bss o los datos, pero depende del enlazador decidir dónde irá. Esto le permite tener la misma variable definida en diferentes unidades de compilación. Por lo que sé, esto es principalmente para permitir algunos archivos de encabezado antiguos que tenían int foo; en ellos en lugar de extern int foo; .

Así es como funciona:

$ cat > a.c int foo; $ cat > b.c int foo; $ cat > main.c extern int foo; int main(int argc, char **argv) { return foo; } $ cc -c a.c && cc -c b.c && cc -c main.c && cc -o x a.o b.o main.o $ objdump -t a.o | grep foo 0000000000000004 O *COM* 0000000000000004 foo $ objdump -t b.o | grep foo 0000000000000004 O *COM* 0000000000000004 foo $ objdump -t x | grep foo 0000000000600828 g O .bss 0000000000000004 foo $

Tenga en cuenta que esto solo funciona cuando se inicializa como máximo una de las variables en las diferentes unidades de compilación.

$ echo "int foo = 0;" > a.c $ cc -c a.c && cc -c b.c && cc -c main.c && cc -o x a.o b.o main.o $ echo "int foo = 0;" > b.c $ cc -c a.c && cc -c b.c && cc -c main.c && cc -o x a.o b.o main.o b.o:(.bss+0x0): multiple definition of `foo'' a.o:(.bss+0x0): first defined here collect2: ld returned 1 exit status $

Esto es algo aterrador, compatibilidad con sistemas antiguos y nunca debes confiar en ello. Haga las cosas correctamente: solo una definición de variables globales en todas las unidades de compilación, declare que está fuera de ella en cualquier otro lugar a través de un encabezado.


Si permite el uso common durante la vinculación, diferentes unidades pueden declarar la misma variable y el enlazador las ubicará en la misma ubicación. Los tipos ni siquiera tienen que ser iguales, por lo que es una especie de unión de tiempo de enlace. Esta es la característica COMMON de Fortran. Si no permite common enlace common con C, entonces, tal situación resultará en un error de tiempo de enlace. Dicha vinculación common solo es posible para globales sin inicializar, porque de lo contrario no está claro qué inicialización debe tomarse.

Los globals que van a bss son solo globals no inicializados que C define como inicializados a 0. La mayoría de los formatos de objetos admiten secciones donde solo se proporciona el tamaño y el cargador llenará toda la sección con ceros.

PD: Si usa gcc , puede usar la opción -fno-common para forzar símbolos common a la sección bss , que, como argumenta Art, es una práctica recomendable y conveniente.


// file a.c // file-scope int a = 0; // goes into BSS

después de la compilación de ac en el archivo de objeto ao , a símbolo entra en la sección BSS.

// file b.c // file-scope int b; // goes into COMMON section

después de compilar bc en el archivo de objeto bo , el símbolo b entra en la sección COMÚN.

Después de vincular ao y bo , los símbolos a y b pasan a la sección BSS. Los símbolos comunes solo existen en archivos de objetos, no en archivos ejecutables. La idea de los símbolos COMUNES en Unix es permitir múltiples definiciones externas de una misma variable (en diferentes unidades de compilación) bajo un solo símbolo común bajo ciertas condiciones.