2012-08-27 13 views
6

Quiero entender exactamente dónde se almacenan las variables globales en mi programa. En la pila? En el montón? ¿En algún otro lugar?La variable global parece no ocupar ningún espacio de memoria

Así que para que escribí este pequeño código:

int global_vector[1000000]; 
int main() { 
    global_vector[0] = 1; // just to avoid a compilation warning 
    while(true); // to give me time to check the amount of RAM used by my program 
    return 0; 
} 

No importa lo grande que ponga global_vector, el programa sólo utiliza un muy pequeña cantidad de memoria RAM. No entiendo el motivo de esto. ¿Podría alguien explicar por favor?

+5

Dudo que esto sea relevante ya que es una matriz estática, pero ¿intentó 'memset'ting toda la matriz a cero? – Mysticial

+2

En realidad esto es completamente relevante.Usando 'memset' el programa pasó de usar 92K a 381.6M. –

+0

En ese caso, la respuesta de templatetypedef es correcta. – Mysticial

Respuesta

11

Esto depende completamente de la implementación, pero generalmente las variables globales se almacenan en un segmento de memoria especial que está separado de la pila y el montón. Esta memoria podría asignarse como un búfer de tamaño fijo dentro del ejecutable, o en un segmento que el sistema operativo le asigna al inicio.

La razón por la que no está viendo el aumento en el uso de la memoria probablemente tiene que ver con la forma en que el sistema operativo maneja la memoria virtual. Como una optimización, el sistema operativo en realidad no dará ninguna memoria al programa para ese conjunto gigante a menos que realmente lo use. Intente cambiar su programa a for-loop sobre todo el contenido de la matriz y vea si eso hace que el uso de RAM aumente. (También es posible que el optimizador en su compilador elimine la matriz gigante, ya que está casi sin usar. Poner un ciclo para leer/escribir todos los valores también puede forzar al compilador a mantenerlo).

Espero que esto ayude!

+0

Exactamente. Después de la sugerencia de Mysticial, utilicé 'memset' para establecer todos los valores de la matriz a cero y eso hizo que el uso de la memoria RAM saltara drásticamente. –

+0

El hecho de que una matriz ** global ** esté "casi" sin usar es irrelevante ... el * compilador * normalmente no puede realizar optimizaciones globales. Aquí hay una excepción porque es 'main' y se devuelve antes de usar la matriz, por lo que ningún código en otras unidades de compilación podría usarla, pero hacer tal optimización no tiene sentido. –

5

El optimizador probablemente esté eliminando la matriz por completo ya que nunca la usa.

+1

Pero lo hice. ¿Qué pasa con la primera línea después de 'int main()'? –

+0

@ curvatura: solo usaste un elemento en él. Nunca subestimes el poder del optimizador (ten en cuenta que realmente no se ha comprobado) – SLaks

+2

@curvature Lo que hizo no tiene ningún efecto observable, por lo que el compilador podría eliminarlo. – ollb

3

Las variables globales que no tienen inicializadores explícitos, como el tuyo en este caso, se inicializan a 0 de manera predeterminada. Se colocan en un área de memoria llamada .bss segment, y no se almacenan datos adicionales en el archivo de objeto/archivo ejecutable que indica el valor inicial de los datos (a diferencia de los datos inicializados explícitamente, que tienen que tener su valor inicial almacenado en algún lugar).

Cuando el sistema operativo carga el programa, lee las descripciones de todos los segmentos y asigna memoria para eso. Como sabe que el segmento .bss se inicializa a todos los 0, puede hacer un truco furtivo para evitar tener que asignar realmente toneladas de memoria y luego inicializarlo a todos los 0: asigna espacio de direcciones para el segmento en la página del proceso tabla, pero todas las páginas apuntan a la misma página, llena de 0.

Esa única página cero también está configurada como de solo lectura. Luego, si y cuando el proceso escribe en algunos datos en el segmento .bss, se produce un error de página. El sistema operativo intercepta el error de página, se da cuenta de lo que está sucediendo y, a continuación, asigna memoria única para esa página de datos. A continuación, reinicia las instrucciones, y el código continúa de manera feliz, como si la memoria se hubiera asignado todo el tiempo.

Por lo tanto, el resultado final es que si tiene una matriz o variable global inicializada cero, cada fragmento de tamaño de página (normalmente 4 KB) que nunca se escribe nunca tendrá realmente memoria asignada para él.

Nota: Estoy siendo un poco confuso aquí con la palabra "asignado". Si profundizas en este tipo de cosas, es probable que encuentres palabras como "reservado" y "comprometido". Consulte this question y this page para obtener más información sobre esos términos en el contexto de Windows.

Cuestiones relacionadas