En informática , la gestión manual de la memoria se refiere al uso de instrucciones manuales por parte del programador para identificar y desasignar objetos no utilizados o basura . Hasta mediados de la década de 1990, la mayoría de los lenguajes de programación utilizados en la industria admitían la gestión manual de memoria, aunque la recolección de basura existe desde 1959, cuando se introdujo con Lisp . Hoy, sin embargo, los lenguajes con recolección de basura como Java son cada vez más populares y los lenguajes Objective-C y Swift brindan una funcionalidad similar a través del Conteo automático de referencias.. Los principales idiomas gestionados manualmente todavía en uso generalizado hoy en día son C y C ++ - ver la asignación de memoria dinámica C .
Descripción
Todos los lenguajes de programación utilizan técnicas manuales para determinar cuándo asignar un nuevo objeto de la tienda gratuita. C usa la malloc
función; C ++ y Java usan el new
operador; y muchos otros lenguajes (como Python) asignan todos los objetos de la tienda gratuita. Determinar cuándo se debe crear un objeto ( creación de objeto ) es generalmente trivial y sin problemas, aunque técnicas como las agrupaciones de objetos significan que un objeto puede crearse antes de su uso inmediato. El verdadero desafío es la destrucción de objetos : determinar cuándo un objeto ya no es necesario (es decir, si es basura) y organizar su almacenamiento subyacente para que se devuelva a la tienda gratuita para su reutilización. En la asignación de memoria manual, esto también lo especifica manualmente el programador; a través de funciones como free()
en C, o el delete
operador en C ++, esto contrasta con la destrucción automática de objetos contenidos en variables automáticas , en particular variables locales (no estáticas) de funciones, que se destruyen al final de su alcance en C y C ++.
Gestión y corrección manual
Se sabe que la administración de memoria manual permite varias clases importantes de errores en un programa cuando se usa incorrectamente, en particular violaciones de la seguridad de la memoria o pérdidas de memoria . Éstos son una fuente importante de errores de seguridad .
- Cuando un objeto no utilizado nunca se devuelve a la tienda gratuita, esto se conoce como pérdida de memoria . En algunos casos, las pérdidas de memoria pueden ser tolerables, como un programa que "pierde" una cantidad limitada de memoria durante su vida útil, o un programa de ejecución corta que depende de un sistema operativo para desasignar sus recursos cuando finaliza. Sin embargo, en muchos casos se producen pérdidas de memoria en programas de larga ejecución y, en tales casos, se filtra una cantidad ilimitada de memoria. Cuando esto ocurre, el tamaño de la tienda gratuita disponible continúa disminuyendo con el tiempo; cuando finalmente se agota, el programa se bloquea.
- Se puede producir una falla catastrófica del sistema de administración de memoria dinámica cuando la memoria de respaldo de un objeto se elimina más de una vez; un objeto se destruye explícitamente más de una vez; cuando, mientras usa un puntero para manipular un objeto no asignado en la tienda gratuita, un programador intenta liberar la memoria de respaldo del objeto objetivo de dicho puntero; o cuando, mientras manipula un objeto a través de un puntero a otra área arbitraria de la memoria administrada por una tarea, hilo o proceso externo desconocido, un programador corrompe el estado de ese objeto, posiblemente de tal manera que escriba fuera de sus límites y corrompa sus datos de gestión de memoria. El resultado de tales acciones puede incluir corrupción del montón , destrucción prematura de un objeto diferente (y recién creado) que ocupa la misma ubicación en la memoria que el objeto eliminado en varias ocasiones, el programa se bloquea debido a una falla de segmentación (violación de la protección de la memoria ) y otras formas de comportamiento indefinido .
- Los punteros a objetos eliminados se convierten en punteros salvajes si se usan después de la eliminación; intentar utilizar estos indicadores puede resultar en errores difíciles de diagnosticar.
Se sabe que los lenguajes que utilizan exclusivamente la recolección de basura evitan las dos últimas clases de defectos. Las pérdidas de memoria aún pueden ocurrir (y las pérdidas limitadas ocurren con frecuencia con la recolección de basura generacional o conservadora), pero generalmente son menos graves que las pérdidas de memoria en los sistemas manuales.
La adquisición de recursos es inicialización
La gestión de memoria manual tiene una ventaja de corrección, que es que permite la gestión automática de recursos a través del paradigma de adquisición de recursos es inicialización (RAII).
Esto surge cuando los objetos poseen recursos del sistema escasos (como recursos gráficos, identificadores de archivos o conexiones de bases de datos) que deben abandonarse cuando se destruye un objeto, cuando la vida útil de la propiedad del recurso debe estar vinculada a la vida útil del objeto. Los lenguajes con administración manual pueden arreglar esto adquiriendo el recurso durante la inicialización del objeto (en el constructor) y liberando durante la destrucción del objeto (en el destructor ), lo que ocurre en un momento preciso. Esto se conoce como adquisición de recursos es inicialización.
Esto también se puede utilizar con el recuento de referencia determinista . En C ++, esta capacidad se utiliza aún más para automatizar la desasignación de memoria dentro de un marco que de otro modo sería manual, el uso de la shared_ptr
plantilla en la biblioteca estándar del lenguaje para realizar la gestión de la memoria es un paradigma común. Sin embargo, noshared_ptr
es adecuado para todos los patrones de uso de objetos.
Este enfoque no se puede utilizar en la mayoría de los lenguajes de recolección de basura, en particular el seguimiento de recolectores de basura o el recuento de referencias más avanzado, debido a que la finalización no es determinista y, a veces, no ocurre en absoluto. Es decir, es difícil definir (o determinar) cuándo o si se puede llamar a un método de finalizador ; esto se conoce comúnmente como el problema del finalizador . Java y otros lenguajes GC con frecuencia usan la administración manual para los escasos recursos del sistema además de la memoria a través del patrón de disposición : se espera que cualquier objeto que administre recursos implemente el dispose()
método, que libera dichos recursos y marca el objeto como inactivo. Se espera que los programadores invoquen dispose()
manualmente según corresponda para evitar la "fuga" de recursos gráficos escasos. Dependiendo del finalize()
método (cómo Java implementa los finalizadores) para liberar recursos gráficos se considera una práctica de programación deficiente entre los programadores de Java y, de manera similar __del__()
, no se puede confiar en el método análogo en Python para liberar recursos. Para los recursos de pila (recursos adquiridos y liberados dentro de un solo bloque de código), esto se puede automatizar mediante varias construcciones de lenguaje, como Python with
, C # using
o Java try
-with-resources.
Actuación
Muchos defensores de la gestión de memoria manual argumentan que ofrece un rendimiento superior en comparación con técnicas automáticas como la recolección de basura . Tradicionalmente, la latencia era la mayor ventaja, pero ya no es así. La asignación manual frecuentemente tiene una localidad de referencia superior . [ cita requerida ]
También se sabe que la asignación manual es más apropiada para sistemas donde la memoria es un recurso escaso, debido a una recuperación más rápida. Los sistemas de memoria pueden y lo hacen con frecuencia "thrash" cuando el tamaño del conjunto de trabajo de un programa se acerca al tamaño de la memoria disponible; Los objetos no utilizados en un sistema de recolección de basura permanecen en un estado no recuperado durante más tiempo que en los sistemas administrados manualmente, porque no se recuperan de inmediato, lo que aumenta el tamaño efectivo del conjunto de trabajo.
La gestión manual tiene una serie de desventajas de rendimiento documentadas :
- Las llamadas a
delete
y tales incurren en gastos generales cada vez que se realizan, estos gastos generales se pueden amortizar en ciclos de recolección de basura. Esto es especialmente cierto en las aplicaciones multiproceso, donde las llamadas de eliminación deben sincronizarse. - La rutina de asignación puede ser más complicada y lenta. Algunos esquemas de recolección de basura, como aquellos con compactación de pila , pueden mantener el almacenamiento libre como una simple matriz de memoria (a diferencia de las complicadas implementaciones requeridas por los esquemas de administración manual).
La latencia es un punto debatido que ha cambiado con el tiempo, ya que los primeros recolectores de basura y las implementaciones simples funcionan muy mal en comparación con la administración de memoria manual, pero los recolectores de basura modernos y sofisticados a menudo funcionan tan bien o mejor que la administración de memoria manual.
La asignación manual no sufre los largos tiempos de "pausa" que ocurren en la recolección de basura simple de detener el mundo, aunque los recolectores de basura modernos tienen ciclos de recolección que a menudo no se notan.
La gestión de memoria manual y la recolección de basura sufren tiempos de desasignación potencialmente ilimitados: la gestión de memoria manual porque la desasignación de un solo objeto puede requerir la desasignación de sus miembros, y recursivamente los miembros de sus miembros, etc., mientras que la recolección de basura puede tener ciclos de recolección largos. Esto es especialmente un problema en los sistemas de tiempo real , donde los ciclos de cobranza ilimitados son generalmente inaceptables; La recolección de basura en tiempo real es posible pausando el recolector de basura, mientras que la administración de memoria manual en tiempo real requiere evitar grandes desasignaciones o pausar manualmente la desasignación.
Referencias
- Berger, ED; Zorn, BG; McKinley, KS (noviembre de 2002). "Reconsideración de la asignación de memoria personalizada" (PDF) . Actas de la 17ª conferencia ACM SIGPLAN sobre programación, sistemas, lenguajes y aplicaciones orientados a objetos . págs. 1-12. CiteSeerX 10.1.1.119.5298 . doi : 10.1145 / 582419.582421 . ISBN 1-58113-471-1. Parámetro desconocido
|conference=
ignorado ( ayuda )
enlaces externos
- La referencia de gestión de la memoria
- Richard Jones y Rafael Lins, Garbage Collection: Algorithms for Automated Dynamic Memory Management , Wiley and Sons (1996), ISBN 0-471-94148-4