2010-02-25 14 views
5

Se produce una pérdida de memoria, cuando hay memoria no utilizada en la aplicación y GC puede recopilarla, normalmente ocurre si en algún lugar de la aplicación guardamos una referencia no deseada de un objeto, y GC podrá encontrar la ruta (directa e indirecta) puede liberar este objeto, pero todo esto es cierto sobre el tipo de referencia que significa en la asignación de la memoria Heap.¿Es posible que la pérdida de memoria también ocurra en la pila en .NET?

Pero, ¿qué pasa con la pila? Y hasta donde sé GC no se encargará de limpiar la pila, automáticamente se limpiará cuando vuelva la función.

Así que mi pregunta es si hay alguna posibilidad de que la pérdida de memoria se produzca también en la pila ?, si es así, ¿en qué situación y cuáles son las mejores prácticas para evitar este tipo de pérdidas?

Respuesta

2

Si está escribiendo funciones recursivas que mantienen referencias locales de pila a datos grandes que no son necesarios en llamadas sub recursivas, entonces este es un tipo de fuga de espacio, pero es muy raro que esto sea un problema en práctica.

De manera más general, si usted tiene algo así como

Main() { 
    var s = ReadInAGiganticString(); // say 10 Megs long 
    Server(s.Substring(0,5));   // but I only care about first 5 chars 
} 
Server(s) { 
    while(true) { ... }    // but 10M is on stack forever 
} 

entonces esto es una especie de pila en el espacio de fugas, pero de nuevo, es poco probable en la práctica. La solución es fácil:

Main() { 
    var s = ReadInAGiganticString(); 
    var t = s.Substring(0,5); 
    s = null;       // the fix 
    Server(t); 
} 
Server(s) { 
    while(true) { ... } 
} 

En general, si alguna vez tiene una variable gigante en la pila de la derecha antes de una llamada que va a durar 'mucho tiempo' y la variable ya no se utiliza, se puede anular a cabo para asegurar que pueda ser GC antes de entrar en la llamada 'larga'.

(Es posible que un optimizador puede hacer esto por usted, basado en el análisis de accesibilidad.)

Tenga en cuenta que la respuesta anterior es para referencias a objetos asignados montón que tienen sus raíces en la pila. Si, por otro lado, tienes memoria asignada por pila (por ejemplo, una estructura gigantesca o thingal stackalloc), entonces la solución no es tan fácil, pero esto es aún más raro en la práctica (¿quién alguna vez creó estructuras gigantes?).

+1

Solo la referencia a la cadena está en la pila, la cadena misma reside en el montón. –

0

Las variables que se asignan en la pila se destruyen después de que finaliza el bloque. Por lo tanto, no es posible que se acumule pérdida de memoria. La práctica de la cama es crear una variable que se usa solo en un bloque dado fuera de ese bloque

0

Como dices, el GC no limpia la pila. Sin embargo, el espacio utilizado por la pila se recupera durante el desenrollado. Entonces, cuando la pila se abre, el puntero de la pila se mueve "hacia atrás" y, por lo tanto, el espacio puede reutilizarse.

Si se queda sin espacio en la pila, se elevará StackOverflowException. Por lo general, se debe a un error de programación con recursividad ilimitada.

0

Sin saber demasiado sobre el funcionamiento interno de .NET, diría que si tiene una fuga de pila, tendrá un programa bloqueado ya que la dirección de retorno de la función/método también se almacena en la pila (lo más probable) .

Si su pila se desalinea de alguna manera, usted tendría problemas mucho más grandes que una pérdida de memoria.

Normalmente los parámetros del método y los valores devueltos se almacenan en la pila (si no están optimizados para enviarse a través de los registros de la CPU).

0

No, siempre que utilice un código de seguridad, las pérdidas de memoria no pueden ocurrir para las variables de la pila.

1

Se puede producir una pérdida de memoria si no se liberan correctamente los recursos no administrados. Por lo tanto, me temo que si envía un objeto administrado a un método y este objeto envuelve un recurso no administrado y no libera correctamente el recurso no administrado, habrá una pérdida de memoria. La pila liberará la referencia administrada, pero el recurso no administrado permanecerá activo.

Cuestiones relacionadas