Ir al contenido

Diferencia entre revisiones de «Fuga de memoria»

De Wikipedia, la enciclopedia libre
Contenido eliminado Contenido añadido
WikitanvirBot (discusión · contribs.)
m r2.7.1) (robot Añadido: tr:Bellek sızıntısı
Aosbot (discusión · contribs.)
m Añadiendo plantilla Listaref
 
(No se muestran 23 ediciones intermedias de 20 usuarios)
Línea 1: Línea 1:
{{referencias|t=20130110|informática}}
Una '''fuga de memoria''' (más conocido por el término [[Idioma inglés|inglés]] ''memory leak'') es un [[error de software]] que ocurre cuando un [[bloque de memoria]] reservada no es liberada en un [[software|programa]] de computación. Comúnmente ocurre porque se pierden todas las referencias a esa área de memoria antes de haberse liberado.
Una '''fuga de memoria''' (más conocido por el término [[Idioma inglés|inglés]] ''memory leak'') es un [[error de software]] que ocurre cuando un [[bloque de memoria]] reservada no es liberada en un [[software|programa]] de computación. Comúnmente ocurre porque se pierden todas las referencias a esa área de memoria antes de haberse liberado.


Dependiendo de la cantidad de memoria perdida y el tiempo que el programa siga en [[tiempo de ejecución|ejecución]], este problema puede llevar al agotamiento de la memoria disponible en la [[computadora]].
Dependiendo de la cantidad de memoria perdida y el tiempo que el programa siga en [[tiempo de ejecución|ejecución]], este problema puede llevar al agotamiento de la memoria disponible en la [[computadora]]. Una pérdida de memoria puede provocar un aumento en el uso de la memoria, el tiempo de ejecución del rendimiento y puede afectar negativamente a la experiencia del usuario. <ref>Rudafshani, Masoomeh, and Paul A. S. Ward. “LeakSpot: Detection and Diagnosis of Memory Leaks in JavaScript Applications.” Software, practice & experience 47.1 (2017): 97–123. Web.</ref>


Este problema se da principalmente en aquellos [[lenguajes de programación]] en los que el manejo de memoria es manual (C o C++ principalmente), y por lo tanto es el programador el que debe saber en qué momento exacto puede liberar la memoria. Otros lenguajes utilizan un [[recolector de basura]] o [[conteo de referencias]] que automáticamente efectúa esta liberación. Sin embargo todavía es posible la existencia de fugas en estos lenguajes si el programa acumula referencias a objetos, impidiendo así que el recolector llegue a considerarlos en desuso.


Este problema se da principalmente en aquellos [[lenguajes de programación]] en los que el manejo de memoria es manual ([[C (lenguaje de programación)|C]] o [[C++]] principalmente), y por lo tanto es el programador el que debe saber en qué momento exacto puede liberar la memoria. Otros lenguajes utilizan un [[recolector de basura]] o [[conteo de referencias]] que automáticamente efectúa esta liberación. Sin embargo todavía es posible la existencia de fugas en estos lenguajes si el programa acumula referencias a objetos, impidiendo así que el recolector llegue a considerarlos en desuso.
Existen varias formas de luchar contra este problema. Una forma es el uso de un recolector de basura incluso en el caso en el que éste no sea parte estándar del lenguaje. El más conocido recolector de basura usado de esta manera es el [http://www.hpl.hp.com/personal/Hans_Boehm/gc/ Boehm-Demers-Weiser conservative garbage collector]. Otras técnicas utilizadas son la adopción de esquemas de [[conteo de referencias]] o el uso de pools de memoria (técnica menos popular, utilizada en el servidor Apache y en el sistema de versiones Subversion).

Existen varias formas de luchar contra este problema. Una forma es el uso de un recolector de basura incluso en el caso en el que este no sea parte estándar del lenguaje. El más conocido recolector de basura usado de esta manera es el [https://web.archive.org/web/20051013094532/http://www.hpl.hp.com/personal/Hans_Boehm/gc/ Boehm-Demers-Weiser conservative garbage collector]. Otras técnicas utilizadas son la adopción de esquemas de [[conteo de referencias]] o el uso de pools de memoria (técnica menos popular, utilizada en el servidor Apache y en el sistema de versiones Subversion).


También hay herramientas para "auscultar" un programa y detectar las fugas. Una de las herramientas más conocidas es [[Valgrind]].
También hay herramientas para "auscultar" un programa y detectar las fugas. Una de las herramientas más conocidas es [[Valgrind]].


== RAII ==
== RAII ==
{{main|Adquirir Recursos es Inicializar}}
{{AP|Adquirir Recursos es Inicializar}}


"'''Adquirir Recursos es Inicializar'''", a menudo referido por sus siglas en inglés '''RAII''' (de "Resource Acquisition Is Initialization"), es un popular [[patrón de diseño]] en varios [[Programación_orientada_a_objetos|lenguajes de programación orientados a objetos]] como [[C++]], y [[Ada_(lenguaje_de_programación)|Ada]]. RAII soluciona las fugas de memoria relacionando objetos con los recursos adquiridos, y automáticamente liberando los recursos cuando los objetos terminan su vida. A diferencia de la [[Recolector_de_basura|recolección de basura]], RAII tiene las ventajas de: saber cuándo los objetos existen y saber cuándo no. Se puede comparar los siguientes ejemplos en C y C++:
"'''Adquirir Recursos es Inicializar'''", a menudo referido por sus siglas en inglés '''RAII''' (de "Resource Acquisition Is Initialization"), es un popular [[patrón de diseño]] en varios [[Programación_orientada_a_objetos|lenguajes de programación orientados a objetos]] como [[C++]], y [[Ada_(lenguaje_de_programación)|Ada]]. RAII soluciona las fugas de memoria relacionando objetos con los recursos adquiridos, y automáticamente liberando los recursos cuando los objetos terminan su vida. A diferencia de la [[Recolector_de_basura|recolección de basura]], RAII tiene las ventajas de: saber cuándo los objetos existen y saber cuándo no. Se puede comparar los siguientes ejemplos en C y C++:


<source lang="c">
<syntaxhighlight lang="c">
/* Versión en C */
/* Versión en C */
#include <stdlib.h>
#include <stdlib.h>
Línea 24: Línea 26:
free(array);
free(array);
}
}
</syntaxhighlight>
</source>


<source lang="cpp">
<syntaxhighlight lang="cpp">
// Versión en C++.
// Versión en C++.
#include <vector>
#include <vector>
Línea 35: Línea 37:
realizar_otras_operaciones();
realizar_otras_operaciones();
}
}
</syntaxhighlight>
</source>


La versión en C requiere que el desarrollador haga la liberación de memoria, a diferencia de la versión en C++. Esto evita la sobrecarga de los esquemas de la [[Recolector_de_basura|recolección de basura]], e incluso puede ser aplicado a otros recursos como:
La versión en C requiere que el desarrollador haga la liberación de memoria, a diferencia de la versión en C++. Esto evita la sobrecarga de los esquemas de la [[Recolector_de_basura|recolección de basura]], e incluso puede ser aplicado a otros recursos como:
* "Handles" a archivos, que la recolección de basura "mark-and-sweep" no maneja tan efectivamente
* "Handles" a archivos, que la recolección de basura "mark-and-sweep" no maneja tan efectivamente.
* Ventanas que han de ser cerradas
* Ventanas que han de ser cerradas.
* Iconos en el área de notificación que han de ser ocultados
* Iconos en el área de notificación que han de ser ocultados.
* Código de sincronización como monitores, secciones críticas, etc. que deben ser liberados para permitir que otros hilos de ejecución("threads") los obtengan
* Código de sincronización como monitores, secciones críticas, etc. que deben ser liberados para permitir que otros hilos de ejecución("threads") los obtengan.
* "Handles" al registro de Windows que están abiertos
* "Handles" al registro de Windows que están abiertos.
* Conexiones de red
* Conexiones de red.
* Objetos GDI de Windows
* Objetos GDI de Windows.
* Acciones a realizar cuando se termina una función (o bloque de código) en cualquier punto posible (la acción la realiza el destructor de un objeto creado cuando empieza la función)
* Acciones a realizar cuando se termina una función (o [[bloque de código]]) en cualquier punto posible (la acción la realiza el destructor de un objeto creado cuando empieza la función).

==Fugas de memoria en lenguajes con recolector de basura==

Las fugas de memoria en lenguajes como [[JavaScript]] también son comunes, por ejemplo pueden ocurrir cuando hay referencias circulares entre los objetos. Por ejemplo un objeto ventana tiene una referencia a cada uno de sus controles (botones, imágenes, etc), a su vez cada control tiene una referencia a la ventana que lo contiene. Los [[Recolector de basura|recolectores de memoria]] que usan [[conteo de referencias]] pueden no darse cuenta de que una ventana ya no es usada porque sigue habiendo referencia a ella (de sus controles).

Estas fugas de memoria son muy comunes cuando se programa en forma despreocupada. Hay técnicas para evitarlas (por ejemplo eliminar alguna de las referencias para cortar el círculo).

En [[JavaScript]] ocurren también referencias circulares cuando se escriben funciones dentro de otras, porque cuando una función es escrita dentro de otra se mantiene una referencia a la que la incluye (para poder usar sus variables). El concepto de [[Clausura (informática)|clausura]] explica estos comportamientos.


==Véase también==
==Véase también==
* [[Memoria dinámica]]
* [[Memoria dinámica (programación)|Memoria dinámica]]
* [[Conteo de referencias]]
* [[Conteo de referencias]]
* [[Recolector de basura]]
* [[Recolector de basura]]


== Referencias ==
[[Categoría:Programación]]
{{listaref}}


{{Control de autoridades}}
[[ar:تسرب الذاكرة]]
[[Categoría:Programación]]
[[cs:Únik paměti]]
[[Categoría:Errores de software]]
[[de:Speicherleck]]
[[en:Memory leak]]
[[fa:کمبود حافظه]]
[[fi:Muistivuoto]]
[[fr:Fuite de mémoire]]
[[he:דליפת זיכרון]]
[[id:Kebocoran Memori]]
[[it:Memory leak]]
[[ja:メモリリーク]]
[[ko:메모리 누수]]
[[lt:Atminties nutekėjimas]]
[[ms:Bocor ingatan]]
[[nl:Geheugenlek]]
[[pl:Wyciek pamięci]]
[[pt:Vazamento de memória]]
[[ru:Утечка памяти]]
[[sk:Memory leak]]
[[tr:Bellek sızıntısı]]
[[zh:内存泄漏]]
[[zh-yue:漏記憶]]

Revisión actual - 11:19 1 dic 2023

Una fuga de memoria (más conocido por el término inglés memory leak) es un error de software que ocurre cuando un bloque de memoria reservada no es liberada en un programa de computación. Comúnmente ocurre porque se pierden todas las referencias a esa área de memoria antes de haberse liberado.

Dependiendo de la cantidad de memoria perdida y el tiempo que el programa siga en ejecución, este problema puede llevar al agotamiento de la memoria disponible en la computadora. Una pérdida de memoria puede provocar un aumento en el uso de la memoria, el tiempo de ejecución del rendimiento y puede afectar negativamente a la experiencia del usuario. [1]


Este problema se da principalmente en aquellos lenguajes de programación en los que el manejo de memoria es manual (C o C++ principalmente), y por lo tanto es el programador el que debe saber en qué momento exacto puede liberar la memoria. Otros lenguajes utilizan un recolector de basura o conteo de referencias que automáticamente efectúa esta liberación. Sin embargo todavía es posible la existencia de fugas en estos lenguajes si el programa acumula referencias a objetos, impidiendo así que el recolector llegue a considerarlos en desuso.

Existen varias formas de luchar contra este problema. Una forma es el uso de un recolector de basura incluso en el caso en el que este no sea parte estándar del lenguaje. El más conocido recolector de basura usado de esta manera es el Boehm-Demers-Weiser conservative garbage collector. Otras técnicas utilizadas son la adopción de esquemas de conteo de referencias o el uso de pools de memoria (técnica menos popular, utilizada en el servidor Apache y en el sistema de versiones Subversion).

También hay herramientas para "auscultar" un programa y detectar las fugas. Una de las herramientas más conocidas es Valgrind.

RAII

[editar]

"Adquirir Recursos es Inicializar", a menudo referido por sus siglas en inglés RAII (de "Resource Acquisition Is Initialization"), es un popular patrón de diseño en varios lenguajes de programación orientados a objetos como C++, y Ada. RAII soluciona las fugas de memoria relacionando objetos con los recursos adquiridos, y automáticamente liberando los recursos cuando los objetos terminan su vida. A diferencia de la recolección de basura, RAII tiene las ventajas de: saber cuándo los objetos existen y saber cuándo no. Se puede comparar los siguientes ejemplos en C y C++:

/* Versión en C */
#include <stdlib.h>

void f(int n)
{
  int* array = calloc(n, sizeof(int));
  realizar_otras_operaciones();
  free(array);
}
// Versión en C++.
#include <vector>

void f(int n)
{
  std::vector<int> array (n);
  realizar_otras_operaciones();
}

La versión en C requiere que el desarrollador haga la liberación de memoria, a diferencia de la versión en C++. Esto evita la sobrecarga de los esquemas de la recolección de basura, e incluso puede ser aplicado a otros recursos como:

  • "Handles" a archivos, que la recolección de basura "mark-and-sweep" no maneja tan efectivamente.
  • Ventanas que han de ser cerradas.
  • Iconos en el área de notificación que han de ser ocultados.
  • Código de sincronización como monitores, secciones críticas, etc. que deben ser liberados para permitir que otros hilos de ejecución("threads") los obtengan.
  • "Handles" al registro de Windows que están abiertos.
  • Conexiones de red.
  • Objetos GDI de Windows.
  • Acciones a realizar cuando se termina una función (o bloque de código) en cualquier punto posible (la acción la realiza el destructor de un objeto creado cuando empieza la función).

Fugas de memoria en lenguajes con recolector de basura

[editar]

Las fugas de memoria en lenguajes como JavaScript también son comunes, por ejemplo pueden ocurrir cuando hay referencias circulares entre los objetos. Por ejemplo un objeto ventana tiene una referencia a cada uno de sus controles (botones, imágenes, etc), a su vez cada control tiene una referencia a la ventana que lo contiene. Los recolectores de memoria que usan conteo de referencias pueden no darse cuenta de que una ventana ya no es usada porque sigue habiendo referencia a ella (de sus controles).

Estas fugas de memoria son muy comunes cuando se programa en forma despreocupada. Hay técnicas para evitarlas (por ejemplo eliminar alguna de las referencias para cortar el círculo).

En JavaScript ocurren también referencias circulares cuando se escriben funciones dentro de otras, porque cuando una función es escrita dentro de otra se mantiene una referencia a la que la incluye (para poder usar sus variables). El concepto de clausura explica estos comportamientos.

Véase también

[editar]

Referencias

[editar]
  1. Rudafshani, Masoomeh, and Paul A. S. Ward. “LeakSpot: Detection and Diagnosis of Memory Leaks in JavaScript Applications.” Software, practice & experience 47.1 (2017): 97–123. Web.