¿Por qué los libros dicen: "el compilador asigna espacio para variables en la memoria". ¿No es el ejecutable el que hace eso? Quiero decir, por ejemplo, si escribo el siguiente programa,
#include <iostream>
using namespace std;
int main()
{
int foo;
return 0;
}
y compilarlo, y obtener un ejecutable (que sea program.exe), ahora, si ejecuto program.exe, este archivo ejecutable ordenará asignar un espacio para la variable foo. ¿No? Explique por qué los libros siguen diciendo: "el compilador hará esto ... hará eso".
sizeof
pregunta ahora se encuentra en ¿Por qué sizeof se llama operador de tiempo de compilación?Respuestas:
Tienes razón en que el compilador como tal desaparece cuando tu programa realmente se ejecuta. Y si se ejecuta en una máquina diferente, el compilador ya no está disponible.
Supongo que esto es para hacer una distinción clara entre la memoria realmente asignada por su propio código. El compilador insertará algún código en su programa que haga la asignación de memoria (como usar comandos nuevos, malloc o similares).
Entonces, los libros usan "el compilador hace esto o aquello" a menudo para decir que el compilador agregó algún código que no se menciona explícitamente en sus archivos de código. Es cierto que esto no es exactamente lo que está sucediendo. Desde este punto de vista, muchas cosas mencionadas en los tutoriales estarían equivocadas, pero necesitarían explicaciones bastante elaboradas.
fuente
malloc
et. Alabama.Depende de la variable. El sistema operativo asigna el montón, el programa asignará pila y el compilador asignará espacio para globales / estáticos, es decir, están integrados en el propio exe. Si asigna 1 MB de memoria global, el tamaño de su archivo exe aumentará en al menos 1 MB
fuente
int test[256][1024]; int main(){ test[0][0]=2; return 0; }
este pequeño programa tiene 1 MB asignado pero solo me genera un archivo de objeto de 1.4 Kb y un ejecutable de 8.4 Kb. Sin embargo, debería usar la cantidad correcta de RAM.int a1=1,a2=2,
... todo el camino hasta ..., a1048576=1048576;
Solo entonces definitivamente obtendrías algo más grande que 1mb, creo.lo que hará el compilador es tomar su código y compilarlo en código máquina. Lo que mencionas es un buen ejemplo donde un compilador solo necesita traducir.
Por ejemplo, cuando escribes
Puede ver eso como 'Le estoy diciendo al compilador que [ en la salida que genera ] solicite que la computadora reserve suficiente memoria RAM para un int al que pueda hacer referencia más tarde. El compilador probablemente usará una identificación de recursos o algún mecanismo para rastrear foo en el código de máquina, ¡puedes usar foo en un archivo de texto en lugar de escribir el ensamblaje! Hurra !
Por lo tanto, también puede ver esto ya que el compilador está escribiendo una carta ( o tal vez una novela / enciclopedia ) a todos los procesadores y dispositivos específicos. La carta está escrita en señales binarias que (generalmente) pueden traducirse a diferentes procesadores cambiando el objetivo. Cualquier 'carta' y / o combo puede enviar todo tipo de solicitudes y / o datos; por ejemplo, asigne espacio para esta variable que utilizó el programador.
fuente
Decir "el compilador asigna memoria" puede no ser fácticamente exacto en el sentido literal, pero es una metáfora que sugiere de la manera correcta.
Lo que realmente sucede es que el compilador crea un programa que asigna su propia memoria. Excepto que no es el programa el que asigna memoria, sino el sistema operativo.
Entonces, lo que realmente sucede es que el compilador crea un programa que describe sus requisitos de memoria y el sistema operativo toma esa descripción y la usa para asignar memoria. Excepto que el sistema operativo es un programa y los programas en realidad no hacen nada, describen un cálculo que realiza la CPU. Excepto que la CPU es realmente solo un circuito electrónico complicado, no un pequeño homónimo antropomorfizado.
Pero tiene sentido pensar en los programas, compiladores y CPU como personas pequeñas que viven dentro de una computadora, no porque realmente lo sean, sino porque es una metáfora que se adapta bien al cerebro humano.
Algunas metáforas funcionan bien para describir cosas en un nivel de abstracción, pero no funcionan tan bien en otro nivel. Si piensa en el nivel del compilador, tiene sentido describir el acto de generar código que dará como resultado que se asigne memoria cuando el programa que se está compilando realmente se ejecuta como "asignación de memoria". Es lo suficientemente cercano como para que cuando pensemos en cómo funciona un compilador, tengamos la idea correcta, y no sea tan largo que olvidemos lo que estábamos haciendo. Si tratamos de usar esa metáfora en el nivel del programa compilado en ejecución, es engañoso de una manera extraña, que es lo que notó.
fuente
Es el compilador quien decide dónde almacenar una variable: puede estar en la pila o en un registro gratuito. Cualquiera sea la decisión de almacenamiento realizada por el compilador, el código de máquina correspondiente para acceder a esa variable se generará y no se puede cambiar en tiempo de ejecución. En este sentido, el compilador se encarga de asignar espacio para las variables y el program.exe final solo actúa ciegamente como un zombie en tiempo de ejecución.
Ahora, no confunda esto con una administración de memoria dinámica diferente como malloc, nueva o puede ser su propia administración de memoria. Los compiladores se ocupan del almacenamiento y acceso variable, pero no le importa lo que significa un valor real en otro marco / biblioteca. Por ejemplo:
En tiempo de ejecución, malloc puede devolver un número arbitrario, pero al compilador no le importa, lo único que le importa es dónde almacenar ese número.
fuente
Una redacción más precisa sería: - "el compilador le dice al cargador que reserve espacio para las variables"
En un entorno C-ish habrá tres tipos de espacio para variables: -
En un sistema operativo moderno, la memoria de almacenamiento dinámico no se reservará sino que se asignará según sea necesario.
fuente
Sí, tiene razón, en este caso (declarando una variable en una función), la oración de su libro probablemente sea incorrecta: cuando declara una variable en una función, se asigna en la pila al ingresar a la función. De todos modos, un compilador debe optimizar la situación: si la función no es recursiva (
main()
es un buen candidato para ello), está bien "asignarla" en tiempo de compilación (en el BSS).(Si tiene curiosidad acerca de dónde residen sus variables, puede verificarlo de una manera sucia (si no desea examinar la estructura del archivo obj, de todos modos, ¿por qué no?), Para que pueda declarar algún tipo diferente de variables: constante, estática, dinámica,
malloc()
asignada , etc., y muestra sus direcciones (use el%X
formateadorprintf()
para una mejor legibilidad). Las variables que residen en la pila tendrán direcciones de memoria muy diferentes).fuente
Lo único que se hará en tiempo de ejecución será aumentar el puntero de la pila en una cierta cantidad. Entonces el compilador decide de antemano:
Este puede llamarse "asignación", pero, por supuesto, durante el tiempo de compilación solo se coloca en el modelo que tiene el compilador del programa en ejecución.
fuente