¿En qué áreas de memoria se dividen cuando se ejecuta un programa C#?
1. Composición básica de la memoria
La memoria programable se divide básicamente en varias partes: área de almacenamiento estático, área de montón y área de pila. Sus funciones son diferentes, y las formas de utilizarlos también lo son.
Área de almacenamiento estático: la memoria se ha asignado cuando se compila el programa y esta memoria existe durante todo el período de ejecución del programa. Almacena principalmente datos estáticos, datos globales y constantes.
Área de pila: al ejecutar una función, se pueden crear en la pila unidades de almacenamiento para variables locales dentro de la función, y estas unidades de almacenamiento se liberan automáticamente cuando finaliza la función. La operación de asignación de memoria de pila está integrada en el conjunto de instrucciones del procesador y es muy eficiente, pero la capacidad de memoria asignada es limitada.
Área de montón: también conocida como asignación de memoria dinámica. Cuando el programa se esté ejecutando, use malloc o new para solicitar memoria de cualquier tamaño. El programador es responsable de liberar la memoria usando free o eliminar en el momento adecuado. La vida útil de la memoria dinámica la podemos determinar nosotros. Si no liberamos la memoria, el programa la liberará al final. Sin embargo, una buena práctica de programación es: si una determinada memoria dinámica ya no se utiliza, es necesario liberarla; de lo contrario, pensamos que se ha producido una pérdida de memoria.
2. Diferencias entre los tres
Usemos fragmentos de código para ver qué operaciones y diferencias se requieren para esas tres partes de la memoria, y a qué se debe prestar atención.
Ejemplo 1: Área de almacenamiento estático y área de pila
char* p = “Hello World1”;
char a[] = “Hello World2”;
p[2] = 'A';
a[2] = 'A';
char* p1 = "Hola mundo1;"
Hay un error en este programa. El error ocurre en la línea de código p[2] = 'A'. ¿Por qué tanto la variable p como la matriz de variables a existen en el área de la pila? en el área de la pila, incluidas las variables definidas en la función main()). Sin embargo, los datos "Hello World1" y los datos "Hello World2" se almacenan en áreas diferentes.
Debido a que los datos "Hello World2" existen en la matriz, estos datos se almacenan en el área de la pila y no hay problema para modificarlos. Debido a que la variable de puntero p solo puede almacenar la dirección de un determinado espacio de almacenamiento, los datos "Hello World1" son una constante de cadena, por lo que se almacenan en el área de almacenamiento estático. Aunque se puede acceder a la tercera unidad de datos en el área de almacenamiento estático a través de p [2], es decir, la unidad de almacenamiento donde se encuentra el carácter 'l'. Sin embargo, debido a que los datos "Hello World1" son una constante de cadena y no se pueden cambiar, se informará un error de memoria cuando el programa se esté ejecutando. Además, si genera py p1 en este momento, encontrará que las direcciones guardadas en py p1 son exactamente las mismas. En otras palabras, sólo se guarda una copia de los mismos datos en el área de datos (consulte la Figura 1-1).
Ejemplo 2: Área de pila y área de montón
char* f1()
{
char* p = NULL; p> p>
char a;
p = &a;
return p;
}
char* f2( )
{
char* p = NULL:
p =(char*) nuevo char[4];
devolver p ;
}
Ambas funciones devuelven la dirección de un determinado espacio de almacenamiento. ¿Cuál es la diferencia entre las dos? Aunque la función f1() devuelve un espacio de almacenamiento, este espacio es un espacio temporal. En otras palabras, este espacio tiene solo un ciclo de vida corto. Su ciclo de vida finaliza cuando se llama a la función f1 () y pierde su valor de vida, es decir, este espacio se libera.
Por lo tanto, al llamar a la función f1(), si existe la siguiente declaración en el programa:
char* p ;
p = f1();
* p = 'a';
En este momento, la compilación no informará ningún error, pero cuando el programa se esté ejecutando, se producirá un error de excepción. Porque operó con una memoria que no debería operarse (es decir, espacio de almacenamiento que se ha liberado). Sin embargo, en comparación, la función f2() no tendrá ningún problema. Debido a que el nuevo comando se aplica al espacio de almacenamiento en el montón. Una vez que la aplicación se realiza correctamente, esta memoria siempre existirá a menos que la elimine o finalice el programa. También se puede entender que la memoria dinámica es una unidad compartida y a la que pueden acceder múltiples funciones simultáneamente. Si necesita devolver varios datos pero no tiene forma, la memoria dinámica será una buena opción. Pero asegúrese de evitar lo siguiente:
void f()
{
…
char * p;
p = (char*)new char[100];
…
}
Este programa hace algo sin sentido y algo que traerá grandes resultados. dañar. Porque, aunque se solicita memoria de montón, p guarda la primera dirección de la memoria de montón. Sin embargo, esta variable es una variable temporal y la variable p desaparece cuando finaliza la llamada a la función. En otras palabras, no existe ninguna variable para almacenar la primera dirección de esta memoria del montón y nunca podremos volver a utilizar esa memoria del montón. Sin embargo, esta parte de la memoria del montón siempre está marcada como utilizada por usted (porque no la eliminó hasta el final del programa, por lo que esta parte de la memoria del montón siempre está marcada como el propietario de su programa actual), y otros procesos o los programas no pueden utilizar. A esto lo llamamos "comportamiento deshonesto" poco ético (no lo usamos, pero no permitimos que otros lo usen) como pérdida de memoria. ¡Esto es un tabú para nosotros, los programadores de C++! ! Asegúrese de evitar que esto suceda.
En resumen, la mayor diferencia entre el área de montón, el área de pila y el área de almacenamiento estático es que el ciclo de vida de la pila es muy corto. Sin embargo, el ciclo de vida del área del montón y el área de almacenamiento estático es equivalente a existir al mismo tiempo que la vida del programa (si no elimina la memoria del montón durante la ejecución del programa), llamamos a este tipo de variables o datos variables o datos globales. Sin embargo, el uso del espacio de memoria en el área del montón es más flexible porque le permite liberarlo en cualquier momento cuando ya no lo necesite, mientras que el área de almacenamiento estático siempre existirá durante todo el ciclo de vida del programa.
Este tema nuestro sólo analiza brevemente los componentes básicos de la memoria y las cuestiones a las que se debe prestar atención al utilizarlos. El análisis y discusión de la memoria recorrerá todos nuestros temas futuros, por eso es la primera conferencia.