Luego de de esta larga selección de datos resolvimos esta problema que presentan ciertos de nuestros lectores. Te regalamos la respuesta y esperamos que sea de gran apoyo.
Solución:
Esta es una pregunta estándar de la entrevista:
Asignación de memoria dinámica
¿Se asigna memoria en tiempo de ejecución usando calloc()
, malloc()
y amigos. A veces también se le llama memoria ‘montón’, aunque no tiene nada que ver con la estructura de datos del montón. árbitro.
int * a = malloc(sizeof(int));
La memoria del montón es persistente hasta free()
se llama. En otras palabras, usted controla la vida útil de la variable.
Asignación automática de memoria
Esto es lo que se conoce comúnmente como memoria de ‘pila’ y se asigna cuando ingresa un nuevo alcance (generalmente cuando se inserta una nueva función en la pila de llamadas). Una vez que se sale del alcance, los valores de las direcciones de memoria automáticas no están definidos y es un error acceder a ellos.
int a = 43;
Tenga en cuenta que alcance no significa necesariamente función. Los ámbitos se pueden anidar dentro de una función, y la variable estará dentro del ámbito solo dentro del bloque en el que se declaró. Tenga en cuenta también que no se especifica dónde se asigna esta memoria. (En un cuerdo sistema estará en la pila, o registros para optimización)
Asignación de memoria estática
Se asigna en tiempo de compilación*y la vida útil de una variable en static la memoria es la vida útil del programa.
C ª, static la memoria se puede asignar usando el static
palabra clave. El alcance es solo la unidad de compilación.
Las cosas se ponen más interesantes cuando extern
se considera la palabra clave. Cuando un extern
variable es definido el compilador le asigna memoria. Cuando un extern
variable es declarado, el compilador requiere que la variable sea definido en otra parte. No declarar / definir extern
las variables causarán problemas de vinculación, mientras que la falla al declarar / definir static
las variables causarán problemas de compilación.
en el alcance del archivo, el static la palabra clave es opcional (fuera de una función):
int a = 32;
Pero no en el alcance de la función (dentro de una función):
static int a = 32;
Técnicamente, extern
y static
son dos clases separadas de variables en C.
extern int a; /* Declaration */
int a; /* Definition */
*Notas sobre static asignación de memoria
Es algo confuso decir que static la memoria se asigna en el momento de la compilación, especialmente si empezamos a considerar que la máquina de compilación y la máquina host podrían no ser iguales o ni siquiera estar en la misma arquitectura.
Puede ser mejor pensar que la asignación de static la memoria es manejada por el compilador en vez de asignado en tiempo de compilación.
Por ejemplo, el compilador puede crear una gran data
sección en el binario compilado y cuando el programa se carga en la memoria, la dirección dentro del data
segmento del programa se utilizará como la ubicación de la memoria asignada. Esto tiene la marcada desventaja de hacer que el binario compilado sea muy grande si usa muchos static memoria. Es posible escribir un binario de varios gigabytes generado a partir de menos de media docena de líneas de código. Otra opción es que el compilador inyecte código de inicialización que asignará memoria de alguna otra forma antes de que se ejecute el programa. Este código variará según la plataforma de destino y el sistema operativo. En la práctica, los compiladores modernos utilizan la heurística para decidir cuál de estas opciones utilizar. Puede probar esto usted mismo escribiendo un pequeño programa en C que asigne una gran static array de elementos de 10k, 1m, 10m, 100m, 1G o 10G. Para muchos compiladores, el tamaño binario seguirá creciendo linealmente con el tamaño del arrayy pasado cierto punto, volverá a encogerse a medida que el compilador utilice otra estrategia de asignación.
Registrar memoria
La última clase de memoria son las variables de ‘registro’. Como era de esperar, las variables de registro deben asignarse en el registro de una CPU, pero la decisión se deja en manos del compilador. No puede convertir una variable de registro en una referencia utilizando address-of.
register int meaning = 42;
printf("%pn",&meaning); /* this is wrong and will fail at compile time. */
La mayoría de los compiladores modernos son más inteligentes que usted a la hora de elegir qué variables deben incluirse en los registros 🙂
Referencias:
- El manual de libc
- El lenguaje de programación C de K&R, Apéndice A, Sección 4.1, “Clase de almacenamiento”. (PDF)
- Estándar C11, sección 5.1.2, 6.2.2.3
- Wikipedia también tiene buenas páginas sobre asignación de memoria estática, asignación de memoria dinámica y asignación de memoria automática.
- La página de asignación de memoria dinámica de C en Wikipedia
- Esta Referencia de administración de memoria tiene más detalles sobre las implementaciones subyacentes para asignadores dinámicos.
Hay tres tipos de asignación: static, automático y dinámico.
Asignación estática significa que la memoria para sus variables se asigna cuando se inicia el programa. El tamaño se fija cuando se crea el programa. Se aplica a variables globales, variables de ámbito de archivo y variables calificadas con static
funciones internas definidas.
Asignación automática de memoria ocurre para (nostatic) variables definidas dentro de funciones, y generalmente se almacena en el apilar (aunque el estándar C no exige que se use una pila). No tiene que reservar memoria adicional usándolos, pero por otro lado, también tiene un control limitado sobre la vida útil de esta memoria. Por ejemplo: las variables automáticas en una función solo están ahí hasta que finaliza la función.
void func()
int i; /* `i` only exists during `func` */
Asignación de memoria dinámica es un poco diferente. Ahora controlas el tamaño exacto y la vida útil de estas ubicaciones de memoria. Si no lo libera, se producirá una pérdida de memoria, lo que puede hacer que su aplicación se bloquee, ya que en algún momento, el sistema no puede asignar más memoria.
int* func()
int* mem = malloc(1024);
return mem;
int* mem = func(); /* still accessible */
En el ejemplo superior, la memoria asignada sigue siendo válida y accesible, aunque la función haya terminado. Cuando haya terminado con la memoria, debe liberarla:
free(mem);
Asignación de memoria estática:
- Las variables se asignan permanentemente
- La asignación está hecha antes de ejecución del programa
- Utiliza la estructura de datos llamada apilar para implementar static asignación
- Menos eficiente
- Hay sin capacidad de reutilización de la memoria
Asignación de memoria dinámica:
- Las variables se asignan solamente si la unidad de programa se activa
- La asignación está hecha durante ejecución del programa
- Utiliza la estructura de datos llamada montón para implementar la asignación dinámica
- Más eficiente
- Hay reutilización de la memoria . La memoria se puede liberar cuando no se requiere
Puedes añadir valor a nuestra información colaborando tu veteranía en las ilustraciones.