Cargando...

Fugas de memoria y análisis con valgrind

Detectar fugas, interpretar informes de valgrind y evitar errores de asignación.

En C++, la gestión dinámica de memoria ofrece una gran flexibilidad al desarrollador, pero un uso incorrecto puede provocar fugas de memoria (memory leaks). Una fuga de memoria ocurre cuando una zona de memoria asignada no se libera, lo que con el tiempo llena la RAM y degrada el rendimiento del programa. En este artículo aprenderemos qué es una fuga de memoria, cómo detectarla y cómo analizarla utilizando la herramienta Valgrind.


1. ¿Qué es una fuga de memoria?

Una fuga de memoria ocurre cuando un bloque de memoria asignado con new o malloc no se libera con delete o free. En ese caso, la memoria permanece ocupada hasta que finaliza el programa y no puede ser utilizada por otros procesos.


#include <iostream>
using namespace std;

void CrearFuga() {
    int *p = new int(42); // Memoria dinámica asignada
    // delete p; // ¡Olvidado!
}

int main() {
    CrearFuga();
    cout << "Programa finalizado." << endl;
}

En este ejemplo, la memoria asignada a p permanece en la RAM hasta que el programa termina. Incluso después de finalizar, la memoria se “pierde” hasta que el sistema operativo la recupera. Este tipo de problema puede causar fallos graves en aplicaciones de servidor que se ejecutan durante mucho tiempo.


2. Consecuencias de una fuga de memoria


3. Situaciones típicas que causan fugas


void CodigoErroneo() {
    int *p = new int[5];
    p = new int[10]; // Se pierde la dirección anterior → fuga de 5 int
    delete[] p;
}

4. ¿Cómo prevenir las fugas de memoria?

Se pueden prevenir las fugas de memoria siguiendo algunos principios básicos:


#include <iostream>
#include <memory>
using namespace std;

void UsoSeguro() {
    auto ptr = make_unique<int>(99);
    cout << *ptr << endl;
} // ptr se libera automáticamente al salir del ámbito

En este ejemplo, gracias a std::unique_ptr, no es necesario llamar manualmente a delete; la memoria se libera automáticamente.


5. Detección de fugas de memoria (Valgrind)

Valgrind es una herramienta de análisis de memoria de código abierto que funciona en Linux. Supervisa todos los bloques de memoria asignados y liberados durante la ejecución del programa y reporta fugas, accesos inválidos y liberaciones dobles.

Instalación (Ubuntu / Debian)


sudo apt update
sudo apt install valgrind

Uso

Después de compilar el programa, puede ejecutarse con Valgrind de la siguiente manera:


g++ -g programa.cpp -o programa
valgrind --leak-check=full ./programa

La opción -g añade símbolos de depuración, lo que permite que Valgrind muestre los números de línea en su salida.


6. Ejemplo de salida de Valgrind

Supongamos que el siguiente programa tiene una fuga de memoria:


#include <iostream>
using namespace std;

int main() {
    int *p = new int[3];
    p[0] = 10;
    p[1] = 20;
    p[2] = 30;
    // delete[] p; // ¡Olvidado!
    return 0;
}

La salida de Valgrind sería:


==1234== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1234==    at 0x4C2FB55: operator new[](unsigned long) (vg_replace_malloc.c:431)
==1234==    by 0x40065A: main (programa.cpp:5)
==1234== LEAK SUMMARY:
==1234==    definitely lost: 12 bytes in 1 blocks

Este informe indica que 12 bytes (3 × int) de memoria no fueron liberados. Gracias al número de línea, es fácil identificar la línea problemática.


7. Otras opciones útiles de Valgrind

OpciónDescripción
--track-origins=yesMuestra dónde se generaron los valores no inicializados.
--show-leak-kinds=allLista todos los tipos de fugas (definitely, indirectly).
--num-callers=20Muestra una pila de llamadas más profunda.
--log-file=valgrind.logGuarda los resultados en un archivo.

8. Herramientas alternativas en Windows


9. Mejores prácticas


10. TL;DR

  • Fuga de memoria = memoria asignada con new pero no liberada con delete.
  • Valgrind es una herramienta potente para detectar fugas de memoria.
  • Pruebe su programa con valgrind --leak-check=full ./programa.
  • En C++ moderno, se recomienda usar std::unique_ptr o std::shared_ptr.
  • En Windows, puede usar Visual Studio Diagnostic Tools o Dr. Memory.
  • Todos los ejemplos pueden ejecutarse en Visual Studio 2022 o GCC 11+.

Artículos relacionados