stack - memory-management - c# get system memory usage - ¿Qué y dónde están la pila y el montón?

c# get memory usage / memory-management / language-agnostic / heap / dynamic-memory-allocation

Los libros de lenguaje de programación explican que los tipos de valor se crean en la pila y los tipos de referencia se crean en el montón , sin explicar cuáles son estas dos cosas. No he leído una explicación clara de esto. Entiendo lo que es una pila . Pero,

RajeshKdev



Answer #1

Proporcionaré un código C simple anotado para ilustrar todo esto.La mejor manera de aprender es ejecutar un programa bajo un depurador y observar el comportamiento.Si prefieres leer python,salta al final de la respuesta :)

// Asignado estáticamente en el segmento de datos cuando el programa / DLL se carga por primera vez
// Desasignado cuando el programa / DLL sale
// alcance: se puede acceder desde cualquier lugar del código
int someGlobalVariable;

// Asignado estáticamente en el segmento de datos cuando el programa se carga por primera vez
// Desasignado cuando el programa / DLL sale
// alcance: se puede acceder desde cualquier lugar de este archivo de código en particular
static int someStaticVariable;

// "someArgument" se asigna en la pila cada vez que se llama a MyFunction
// "someArgument" se desasigna cuando MyFunction regresa
// alcance: solo se puede acceder dentro de MyFunction ()
void MyFunction(int someArgument) {

    // Asignado estáticamente en el segmento de datos cuando el programa se carga por primera vez
    // Desasignado cuando el programa / DLL sale
    // alcance: solo se puede acceder dentro de MyFunction ()
    static int someLocalStaticVariable;

    // Asignado en la pila cada vez que se llama a MyFunction
    // Desasignado cuando regresa MyFunction
    // alcance: solo se puede acceder dentro de MyFunction ()
    int someLocalVariable;

    // Se asigna un * puntero * en la pila cada vez que se llama a MyFunction
    // Este puntero se desasigna cuando regresa MyFunction
    // alcance: solo se puede acceder al puntero dentro de MyFunction ()
    int* someDynamicVariable;

    // Esta línea hace que se asigne espacio para un número entero en el montón
    // cuando se ejecuta esta línea. Tenga en cuenta que esto no es al comienzo de
    // la llamada a MyFunction (), como las variables automáticas
    // alcance: solo el código dentro de MyFunction () puede acceder a este espacio
    // * a través de esta variable en particular *.
    // Sin embargo, si pasa la dirección en otro lugar, ese código
    // puede acceder a él también
    someDynamicVariable = new int;


    // Esta línea desasigna el espacio para el entero en el montón.
    // Si no lo escribimos, la memoria se "filtraría".
    // Note una diferencia fundamental entre la pila y el montón
    // el montón debe gestionarse. La pila se gestiona por nosotros.
    delete someDynamicVariable;

    // En otros casos, en lugar de desasignar este espacio dinámico,
    // podría almacenar la dirección en algún lugar más permanente para usarla más tarde.
    // Algunos idiomas incluso se encargan de la desasignación por ti ... pero
    // siempre necesita ser atendido en tiempo de ejecución por algún mecanismo.

    // Cuando la función regresa, someArgument, someLocalVariable
    // y el puntero someDynamicVariable se desasignan.
    // El espacio apuntado por someDynamicVariable ya estaba
    // desasignado antes de regresar.
    return;
}

// Tenga en cuenta que someGlobalVariable, someStaticVariable y
// someLocalStaticVariable continúan existiendo, y no son
// desasignado hasta que se cierra el programa.

Algunas de las opciones de sintaxis en C/C++agravan este problema;por ejemplo,mucha gente piensa que las variables globales no son "estáticas" debido a la sintaxis que se muestra a continuación.

int var1; // Tiene alcance global y asignación estática
static int var2; // Tiene alcance de archivo y asignación estática

int main() {return 0;}

Algunas personas piensan que estos conceptos son específicos de C/C++.No lo son.Por ejemplo,el ejemplo de Python que aparece a continuación ilustra los tres tipos de asignación (hay algunas diferencias sutiles posibles en los lenguajes interpretados que no voy a mencionar aquí).

from datetime import datetime

class Animal:
    _FavoriteFood = 'Undefined' # _FavoriteFood se asigna estáticamente

    def PetAnimal(self):
        curTime = datetime.time(datetime.now()) # curTime se asigna automáticamente
        print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)

class Cat(Animal):
    _FavoriteFood = 'tuna' # Tenga en cuenta que, dado que anulamos, la clase Cat tiene su propia variable _FavoriteFood asignada estáticamente, diferente de la de Animal

class Dog(Animal):
    _FavoriteFood = 'steak' # Asimismo, la clase Dog obtiene su propia variable estática. Es importante tener en cuenta que esta variable estática se comparte entre todas las instancias de Dog, por lo que no es dinámica.


if __name__ == "__main__":
    whiskers = Cat() # Asignado dinámicamente
    fido = Dog() # Asignado dinámicamente
    rinTinTin = Dog() # Asignado dinámicamente

    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

    Dog._FavoriteFood = 'milkbones'
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

# La salida es:
# Gracias por acariciarme. Pero son las 13: 05: 02.255000, deberías alimentarme. Mi comida favorita es el atún
# Gracias por acariciarme. Pero son las 13: 05: 02.255000, deberías alimentarme. Mi comida favorita es el bistec
# Gracias por acariciarme. Pero son las 13: 05: 02.255000, deberías alimentarme. Mi comida favorita es el bistec
# Gracias por acariciarme. Pero son las 13: 05: 02.255000, deberías alimentarme. Mi comida favorita es el atún
# Gracias por acariciarme. Pero son las 13: 05: 02.255000, deberías alimentarme. Mi comida favorita son los huesos de leche
# Gracias por acariciarme. Pero son las 13: 05: 02.256000, deberías alimentarme. Mi comida favorita son los huesos de leche