Saltar al contenido

Diferencia entre la sección de datos y la sección bss en C

Contamos con tu apoyo para compartir nuestros tutoriales referente a las ciencias de la computación.

Solución:

Él .bss Se garantiza que la sección sea todo ceros cuando el programa se cargue en la memoria. Por lo tanto, cualquier dato global que no esté inicializado o inicializado a cero se coloca en el .bss sección. Por ejemplo:

static int g_myGlobal = 0;     // <--- in .bss section

Lo bueno de esto es que la .bss los datos de la sección no tienen que incluirse en el archivo ELF en el disco (es decir, no hay una región completa de ceros en el archivo para el .bss sección). En su lugar, el cargador sabe a partir de los encabezados de sección cuánto asignar para el .bss y simplemente póngalo a cero antes de entregar el control a su programa.

Observe la readelf producción:

[ 3] .data PROGBITS 00000000 000110 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000110 000000 00 WA 0 0 4

.data está marcado como PROGBITS. Eso significa que hay "bits" de datos de programa en el archivo ELF que el cargador necesita leer en la memoria por usted. .bss por otro lado está marcado NOBITSlo que significa que no hay nada en el archivo que deba leerse en la memoria como parte de la carga.


Ejemplo:

// bss.c
static int g_myGlobal = 0;

int main(int argc, char** argv)

   return 0;

compilarlo con $ gcc -m32 -Xlinker -Map=bss.map -o bss bss.c

Mire los encabezados de sección con $ readelf -S bss

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
   :
  [13] .text             PROGBITS        080482d0 0002d0 000174 00  AX  0   0 16
   :
  [24] .data             PROGBITS        0804964c 00064c 000004 00  WA  0   0  4
  [25] .bss              NOBITS          08049650 000650 000008 00  WA  0   0  4
   :

Ahora buscamos nuestra variable en la tabla de símbolos: $ readelf -s bss | grep g_myGlobal

37: 08049654     4 OBJECT  LOCAL  DEFAULT   25 g_myGlobal

Tenga en cuenta que g_myGlobal se muestra como parte de la sección 25. Si miramos hacia atrás en los encabezados de la sección, vemos que 25 es .bss.


Para responder a su verdadera pregunta:

Aquí, en el programa anterior, no tengo ningún dato no inicializado, pero el BSS ha ocupado 8 bytes. ¿Por qué ocupa 8 bytes?

Siguiendo con mi ejemplo, buscamos cualquier símbolo en la sección 25:

$ readelf -s bss | grep 25
     9: 0804825c     0 SECTION LOCAL  DEFAULT    9 
    25: 08049650     0 SECTION LOCAL  DEFAULT   25 
    32: 08049650     1 OBJECT  LOCAL  DEFAULT   25 completed.5745
    37: 08049654     4 OBJECT  LOCAL  DEFAULT   25 g_myGlobal

La tercera columna es el tamaño. Vemos nuestro esperado 4 bytes g_myGlobaly este 1 byte completed.5745. Esta es probablemente una función-static variable de algún lugar en la inicialización del tiempo de ejecución de C; recuerde, muchas "cosas" suceden antes main() se llama alguna vez.

4+1=5 bytes. Sin embargo, si miramos hacia atrás en el .bss encabezado de la sección, vemos la última columna Al es 4. Esa es la alineación de la sección, lo que significa que esta sección, cuando se carga, siempre será un múltiplo de 4 bytes. El siguiente múltiplo de 5 es 8, y es por eso que el .bss la sección es de 8 bytes.


Además Podemos mirar el archivo de mapa generado por el enlazador para ver qué archivos de objetos se colocaron en el resultado final.

.bss            0x0000000008049650        0x8
 *(.dynbss)
 .dynbss        0x0000000000000000        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
 *(.bss .bss.* .gnu.linkonce.b.*)
 .bss           0x0000000008049650        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
 .bss           0x0000000008049650        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crti.o
 .bss           0x0000000008049650        0x1 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtbegin.o
 .bss           0x0000000008049654        0x4 /tmp/ccKF6q1g.o
 .bss           0x0000000008049658        0x0 /usr/lib/libc_nonshared.a(elf-init.oS)
 .bss           0x0000000008049658        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtend.o
 .bss           0x0000000008049658        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crtn.o

Una vez más, la tercera columna es el tamaño.

Vemos 4 bytes de .bss vino de /tmp/ccKF6q1g.o. En este ejemplo trivial, sabemos que es el archivo de objeto temporal de la compilación de nuestro archivo bss.c. El otro 1 byte vino de crtbegin.oque es parte del tiempo de ejecución de C.


Finalmente, dado que sabemos que esta variable bss misteriosa de 1 byte es de crtbegin.oy se llama completed.xxxxsu verdadero nombre es completed y probablemente sea un static dentro de alguna función. Mirando a crtstuff.c encontramos al culpable: un static _Bool completed dentro de __do_global_dtors_aux().

Por definición, el segmento bss ocupa algún lugar en la memoria (cuando se inicia el programa) pero no necesita espacio en disco. Necesita definir alguna variable para llenarla, así que intente

int bigvar_in_bss[16300];
int var_in_data[5] = 1,2,3,4,5;

Es posible que su programa simple no tenga ningún dato en .bssy bibliotecas compartidas (como libc.so) pueden tener "su propia .bss"

Los desplazamientos de archivos y las direcciones de memoria no se relacionan fácilmente.

Lea más sobre la especificación ELF, también use /proc/ (p.ej cat /proc/self/maps mostraría el espacio de direcciones del cat proceso que ejecuta ese comando). Lea también proc(5)

Sección de Reseñas y Valoraciones

Recuerda algo, que tienes la capacidad de reseñar tu experiencia si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *