¿En qué segmento (.BSS, .DATA, otro) de un archivo ejecutable se almacenan las variables estáticas para que no tengan colisión de nombres? 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 compilo ambos archivos y los vinculo a un main que llama a fooTest () y barTest repetidamente, las declaraciones printf se incrementan independientemente. Tiene sentido ya que las variables foo y bar son locales de la unidad de traducción.
Pero, ¿dónde se asigna el almacenamiento?
Para ser claros, se supone que tiene una cadena de herramientas que generaría un archivo en formato ELF. Por lo tanto, yo creo que no tiene que ser un espacio reservado en el archivo ejecutable para aquellas variables estáticas.
Para fines de discusión, supongamos que utilizamos la cadena de herramientas GCC.
c++
c
compiler-construction
Benoit
fuente
fuente
Respuestas:
El destino de sus estadísticas depende de si están inicializadas en cero . los datos estáticos con inicialización cero entran en .BSS (bloque iniciado por símbolo) , los datos con inicialización distinta de cero ingresan .DATA
fuente
.data
datos estáticos sin inicializador.bss
.Cuando un programa se carga en la memoria, se organiza en diferentes segmentos. Uno del segmento es el segmento de DATOS . El segmento de datos se subdivide en dos partes:
segmento de datos inicializados: aquí se almacenan todos los datos globales, estáticos y constantes.
Segmento de datos sin inicializar (BSS): todos los datos sin inicializar se almacenan en este segmento.
Aquí hay un diagrama para explicar este concepto:
Aquí hay un muy buen enlace que explica estos conceptos:
fuente
De hecho, una variable es tupla (almacenamiento, alcance, tipo, dirección, valor):
El alcance local podría significar local para la unidad de traducción (archivo fuente), la función o el bloque dependiendo de dónde esté definido. Para hacer que la variable sea visible para más de una función, definitivamente tiene que estar en el área de DATOS o BSS (dependiendo de si se inicializó explícitamente o no, respectivamente). Luego, se ajusta a todas las funciones o funciones dentro del archivo fuente.
fuente
La ubicación de almacenamiento de los datos dependerá de la implementación.
Sin embargo, el significado de estático es "enlace interno". Por lo tanto, el símbolo es interno a la unidad de compilación (foo.c, bar.c) y no puede ser referenciado fuera de esa unidad de compilación. Por lo tanto, no puede haber colisiones de nombres.
fuente
en el área "global y estática" :)
Hay varias áreas de memoria en C ++:
Consulte aquí para obtener una respuesta detallada a su pregunta:
fuente
No creo que haya una colisión. El uso de estática a nivel de archivo (funciones externas) marca la variable como local a la unidad de compilación actual (archivo). Nunca es visible fuera del archivo actual, por lo que nunca debe tener un nombre que pueda usarse externamente.
El uso de estática dentro de una función es diferente: la variable solo es visible para la función (ya sea estática o no), solo se conserva su valor en las llamadas a esa función.
En efecto, la estática hace dos cosas diferentes dependiendo de dónde se encuentre. Sin embargo, en ambos casos, la visibilidad variable es limitada de tal manera que puede evitar fácilmente conflictos de espacio de nombres al vincular.
Dicho esto, creo que se almacenaría en la
DATA
sección, que tiende a tener variables que se inicializan a valores distintos de cero. Esto es, por supuesto, un detalle de implementación, no algo ordenado por el estándar: solo se preocupa por el comportamiento, no por cómo se hacen las cosas de manera encubierta.fuente
So, how does a segment of memory (Data Segment) store variables that can be accessed from everywhere (global variables) and also those which have limited scope (file scope or function scope in case of static variables)?
Cómo encontrarlo tú mismo con
objdump -Sr
Para comprender realmente lo que está sucediendo, debe comprender la reubicación del enlazador. Si nunca has tocado eso, considera leer esta publicación primero .
Analicemos un ejemplo ELF Linux x86-64 para verlo nosotros mismos:
Compilar con:
Descompilar el código con:
-S
descompila el código con la fuente original entremezclada-r
muestra información de reubicaciónDentro de la descompilación de
f
vemos:y
.data-0x4
dice que irá al primer byte del.data
segmento.El
-0x4
está allí porque estamos usando el direccionamiento relativo RIP, por lo tanto,%rip
en la instrucción yR_X86_64_PC32
.Es necesario porque RIP apunta a la siguiente instrucción, que comienza 4 bytes y luego
00 00 00 00
se reubicará. He explicado esto con más detalle en: https://stackoverflow.com/a/30515926/895245Luego, si modificamos la fuente
i = 1
y hacemos el mismo análisis, concluimos que:static int i = 0
sucede.bss
static int i = 1
sucede.data
fuente
Así es como (fácil de entender):
fuente
Depende de la plataforma y el compilador que esté utilizando. Algunos compiladores se almacenan directamente en el segmento de código. Las variables estáticas siempre son accesibles solo para la unidad de traducción actual y los nombres no se exportan, por lo que nunca se producen colisiones de nombres.
fuente
Los datos declarados en una unidad de compilación irán a .BSS o .Data de la salida de esos archivos. Datos inicializados en BSS, no inicializados en DATA.
La diferencia entre los datos estáticos y globales viene en la inclusión de información de símbolos en el archivo. Los compiladores tienden a incluir la información del símbolo pero solo marcan la información global como tal.
El vinculador respeta esta información. La información de símbolos para las variables estáticas se descarta o se destruye para que las variables estáticas puedan ser referenciadas de alguna manera (con opciones de depuración o símbolo). En ninguno de los casos, las unidades de compilación pueden verse afectadas ya que el vinculador resuelve primero las referencias locales.
fuente
Lo probé con objdump y gdb, aquí está el resultado que obtengo:
Aquí está el resultado objdump
Entonces, es decir, sus cuatro variables se encuentran en la sección de datos del evento con el mismo nombre, pero con un desplazamiento diferente.
fuente
variable estática almacenada en el segmento de datos o segmento de código como se mencionó anteriormente.
Puede estar seguro de que no se asignará en la pila o el montón.
No hay riesgo de colisión ya que la
static
palabra clave define el alcance de la variable como un archivo o función, en caso de colisión hay un compilador / enlazador para advertirle.Un buen ejemplo
fuente
Bueno, esta pregunta es demasiado antigua, pero dado que nadie señala ninguna información útil: consulte la publicación 'mohit12379' que explica el almacén de variables estáticas con el mismo nombre en la tabla de símbolos: http://www.geekinterview.com/question_details/ 24745
fuente
La respuesta bien podría depender del compilador, por lo que probablemente desee editar su pregunta (quiero decir, incluso la noción de segmentos no es obligatoria por ISO C ni ISO C ++). Por ejemplo, en Windows un ejecutable no lleva nombres de símbolos. Un 'foo' se compensaría 0x100, el otro quizás 0x2B0, y el código de ambas unidades de traducción se compila sabiendo las compensaciones para "su" foo.
fuente
ambos se almacenarán de forma independiente, sin embargo, si desea dejarlo claro a otros desarrolladores, es posible que desee envolverlos en espacios de nombres.
fuente
ya sabe que se almacena en bss (inicio de bloque por símbolo) también denominado segmento de datos no inicializado o en segmento de datos inicializado.
tomemos un ejemplo simple
la variable estática anterior no se inicializa, por lo que va al segmento de datos no inicializados (bss).
y, por supuesto, se inicializó en 10, por lo que va al segmento de datos inicializado.
fuente