Pregunta

En qué segmento (.BSS, .De DATOS, otros) de un archivo ejecutable son variables estáticas almacenados, por lo que no tiene nombre de la colisión?Por ejemplo:


foo.c:                         bar.c:
static int foo = 1;            static int foo = 10;
void fooTest() {               void barTest() {
  static int bar = 2;            static int bar = 20;
  foo++;                         foo++;
  bar++;                         bar++;
  printf("%d,%d", foo, bar);     printf("%d, %d", foo, bar);
}                              }

Si puedo compilar los archivos y vincularlo a una principal que llama a fooTest() y barTest en repetidas ocasiones, el printf declaraciones incremento de forma independiente.Tiene sentido, ya que los foo y bar variables son locales a la unidad de traducción.

Pero, ¿dónde está el almacenamiento asignado?

Para ser claros, la suposición es que usted tiene un conjunto de herramientas que sería la salida de un archivo en formato ELF.Por Lo Tanto, Yo creo que no ha para ser un poco de espacio reservado en el archivo ejecutable para aquellas variables estáticas.
Para fines de discusión, permite asumir que el uso de la GCC toolchain.

¿Fue útil?

Solución

Donde su estática depende de si son inicializados a cero o no. inicializados a cero los datos estáticos va en .BSS (Bloque Iniciado por el Símbolo), no inicializados a cero datos va en .DATOS

Otros consejos

Cuando un programa se carga en la memoria, está organizado en segmentos diferentes.Uno de los segmento es Segmento de DATOS.El segmento de Datos se sub-divide en dos partes:

Inicializa segmento de datos: Todo el mundial, estática y constante de los datos son almacenados aquí.
Sin inicializar segmento de datos(BSS): Todos los datos sin inicializar son almacenados en este segmento.

Aquí está un diagrama para explicar este concepto:

enter image description here


aquí es muy bueno link de la explicación de estos conceptos:

http://www.inf.udec.cl/~leo/teoX.pdf

De hecho, una variable de tupla (almacenamiento, alcance, tipo, dirección, valor):

storage     :   where is it stored, for example data, stack, heap...
scope       :   who can see us, for example global, local...
type        :   what is our type, for example int, int*...
address     :   where are we located
value       :   what is our value

Ámbito Local podría significar local para la traslación de la unidad (archivo de origen), la función o el bloque dependiendo de donde definido.Para hacer variable visible a más de una función, que sin duda tiene que ser en cualquiera de los DATOS o de la SEV área (dependiendo de si su inicializado de forma explícita o no, respectivamente).De su ámbito, en consecuencia, a todos los de la función(s) función(s) dentro de los archivo de origen.

La ubicación de almacenamiento de los datos serán dependientes de la implementación.

Sin embargo, el significado de estática es la "relación interna".Por lo tanto, el símbolo es interna a la unidad de compilación (foo.c, bar.c) y no se puede hacer referencia fuera de esa unidad de compilación.Así, no puede haber colisiones de nombres.

No creo que habrá una colisión.Mediante estática en el nivel de archivo (fuera de funciones) marcas de la variable como local en la actual unidad de compilación (archivo).Nunca es visible fuera del archivo actual por lo que nunca tiene que tener un nombre.

Mediante estática dentro de una función es diferente - la variable es visible solo para la función, es sólo su valor se conserva a través de llamadas a la función.

En efecto, la estática de hace dos cosas diferentes dependiendo de donde está.En ambos casos, sin embargo, se limita la visibilidad de la variable para prevenir el espacio de nombres de los enfrentamientos,

Habiendo dicho eso, creo que sería almacena en los DATOS que tiende a tener una variable inicializada.El BSS originalmente representaba byte conjunto de<something> que celebró variables que no se inicializa.

Cómo encontrar a ti mismo con objdump -Sr

Para realmente entender lo que está pasando, usted debe entender enlazador de reubicación.Si nunca has tocado, considere la lectura de este primer post.

Vamos a analizar un Linux x86-64 ELF ejemplo para ver de nosotros mismos:

#include <stdio.h>

int f() {
    static int i = 1;
    i++;
    return i;
}

int main() {
    printf("%d\n", f());
    printf("%d\n", f());
    return 0;
}

Compilar con:

gcc -ggdb -c main.c

Descompilar el código con:

objdump -Sr main.o
  • -S decompile el código con la fuente original entremezclado
  • -r muestra información de relocalización

Dentro de la descompilación de f podemos ver:

 static int i = 1;
 i++;
4:  8b 05 00 00 00 00       mov    0x0(%rip),%eax        # a <f+0xa>
        6: R_X86_64_PC32    .data-0x4

y el .data-0x4 dice que va a ir el primer byte de la .data segmento.

El -0x4 está allí porque estamos usando RIP direccionamiento relativo, por lo tanto el %rip en la instrucción y R_X86_64_PC32.

Es necesario porque RIP puntos a la siguiente la instrucción, que se inicia después de 4 bytes 00 00 00 00 que es lo que se reubican.He explicado en más detalle en: https://stackoverflow.com/a/30515926/895245

Entonces, si queremos modificar el código fuente para i = 1 y hacer el mismo análisis, llegamos a la conclusión de que:

  • static int i = 0 va en .bss
  • static int i = 1 va en .data

en el "global y estática" de la zona :)

hay varias área de memoria en C++

  • montón
  • tienda gratis
  • pila
  • globales y estáticas
  • const

ver aquí para una detallada respuesta a tu pregunta

Depende de la plataforma y el compilador que usas.Algunos compiladores almacenar directamente en el segmento de código.Las variables estáticas son siempre accesibles sólo a la actual unidad de traducción y los nombres no son exportados por lo tanto la razón de las colisiones de nombres no se producirá nunca.

Los datos declarados en una unidad de compilación voy a entrar en el .BSS o el .Los datos de que los archivos de salida.Consultar los datos en la SEV, uninitalised en los DATOS.

La diferencia entre la estática y global de datos viene en la inclusión del símbolo de información en el archivo.Los compiladores suelen incluir el símbolo de información, pero sólo marca el global de la información como tal.

El vinculador respeta esta información.El símbolo de información para las variables estáticas se descarta o se alteran de modo que las variables estáticas todavía puede ser que se hace referencia en alguna manera (con depuración o las opciones de símbolo).En ninguno de los casos puede las unidades de compilación se ve afectado como el enlazador resuelve referencias locales de primera.

variable estática almacenada en el segmento de datos o segmento de código como se mencionó antes.
Usted puede estar seguro de que no va a ser asignado en la pila o montón.
No hay riesgo de colisión, ya que static palabras clave definir el alcance de la variable a ser un archivo o una función, en caso de colisión, no es un compilador/enlazador de advertir acerca de.
Un buen ejemplo

Bien, esta pregunta es un poco demasiado viejo, pero ya que nadie de los puntos de información de utilidad:Compruebe el post por "mohit12379' explicando la tienda de variables estáticas con el mismo nombre en la tabla de símbolos:http://www.geekinterview.com/question_details/24745

He probado con objdump y gdb, aquí está el resultado de lo que obtengo:

(gdb) disas fooTest
Dump of assembler code for function fooTest:
   0x000000000040052d <+0>: push   %rbp
   0x000000000040052e <+1>: mov    %rsp,%rbp
   0x0000000000400531 <+4>: mov    0x200b09(%rip),%eax        # 0x601040 <foo>
   0x0000000000400537 <+10>:    add    $0x1,%eax
   0x000000000040053a <+13>:    mov    %eax,0x200b00(%rip)        # 0x601040 <foo>
   0x0000000000400540 <+19>:    mov    0x200afe(%rip),%eax        # 0x601044 <bar.2180>
   0x0000000000400546 <+25>:    add    $0x1,%eax
   0x0000000000400549 <+28>:    mov    %eax,0x200af5(%rip)        # 0x601044 <bar.2180>
   0x000000000040054f <+34>:    mov    0x200aef(%rip),%edx        # 0x601044 <bar.2180>
   0x0000000000400555 <+40>:    mov    0x200ae5(%rip),%eax        # 0x601040 <foo>
   0x000000000040055b <+46>:    mov    %eax,%esi
   0x000000000040055d <+48>:    mov    $0x400654,%edi
   0x0000000000400562 <+53>:    mov    $0x0,%eax
   0x0000000000400567 <+58>:    callq  0x400410 <printf@plt>
   0x000000000040056c <+63>:    pop    %rbp
   0x000000000040056d <+64>:    retq   
End of assembler dump.

(gdb) disas barTest
Dump of assembler code for function barTest:
   0x000000000040056e <+0>: push   %rbp
   0x000000000040056f <+1>: mov    %rsp,%rbp
   0x0000000000400572 <+4>: mov    0x200ad0(%rip),%eax        # 0x601048 <foo>
   0x0000000000400578 <+10>:    add    $0x1,%eax
   0x000000000040057b <+13>:    mov    %eax,0x200ac7(%rip)        # 0x601048 <foo>
   0x0000000000400581 <+19>:    mov    0x200ac5(%rip),%eax        # 0x60104c <bar.2180>
   0x0000000000400587 <+25>:    add    $0x1,%eax
   0x000000000040058a <+28>:    mov    %eax,0x200abc(%rip)        # 0x60104c <bar.2180>
   0x0000000000400590 <+34>:    mov    0x200ab6(%rip),%edx        # 0x60104c <bar.2180>
   0x0000000000400596 <+40>:    mov    0x200aac(%rip),%eax        # 0x601048 <foo>
   0x000000000040059c <+46>:    mov    %eax,%esi
   0x000000000040059e <+48>:    mov    $0x40065c,%edi
   0x00000000004005a3 <+53>:    mov    $0x0,%eax
   0x00000000004005a8 <+58>:    callq  0x400410 <printf@plt>
   0x00000000004005ad <+63>:    pop    %rbp
   0x00000000004005ae <+64>:    retq   
End of assembler dump.

aquí está el resultado objdump

Disassembly of section .data:

0000000000601030 <__data_start>:
    ...

0000000000601038 <__dso_handle>:
    ...

0000000000601040 <foo>:
  601040:   01 00                   add    %eax,(%rax)
    ...

0000000000601044 <bar.2180>:
  601044:   02 00                   add    (%rax),%al
    ...

0000000000601048 <foo>:
  601048:   0a 00                   or     (%rax),%al
    ...

000000000060104c <bar.2180>:
  60104c:   14 00                   adc    $0x0,%al

Así que, es decir, sus cuatro variables se encuentra en la sección de datos de eventos el mismo nombre, pero con diferentes desplazamiento.

Esta es la manera (fácil de entender):

stack, heap and static data

La respuesta podría muy bien depender de el compilador, por lo que es probable que desee editar tu pregunta (me refiero, incluso la noción de segmentos no es exigido por la ISO C ni ISO C++).Por ejemplo, en Windows un archivo ejecutable no lleva los nombres de los símbolos.Una 'foo' sería compensado 0x100, el otro tal vez 0x2B0, y el código de ambas unidades de traducción se compila conocer los desplazamientos para "su" foo.

ambos van a ser almacenados de forma independiente, sin embargo, si usted quiere dejar claro a los otros desarrolladores que usted podría querer envuélvelo en espacios de nombres.

usted ya sabe de que sea de la tienda en bss(bloque de inicio por símbolo), también conocida como sin inicializar segmento de datos o en inicializado segmento de datos.

veamos un ejemplo sencillo

void main(void)
{
static int i;
}

la anterior variable estática no está inicializado , por lo que va a datos sin inicializar segmento(bss).

void main(void)
{
static int i=10;
}

y, por supuesto, es inicializado por 10, a fin de que se va a inicializar segmento de datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top