Historia del tema:
Los mecanismos de asignación dinámica de memoria aparecieron en C junto con las funciones de la biblioteca estándar malloc/free en <stdlib.h>. Permitieron implementar estructuras de tamaño variable, colecciones complejas y objetos, lo que dio un fuerte impulso al desarrollo del lenguaje y su aplicación en la programación a gran escala.
Problema:
Trabajar con memoria dinámica requiere que el programador tenga control total sobre el ciclo de vida de los objetos. Los errores (fugas de memoria, liberación doble, uso incorrecto de punteros) pueden llevar a fallas o vulnerabilidades (por ejemplo, a exploits a través de errores de use-after-free).
Solución:
— Siempre verifique los valores devueltos por malloc/calloc/realloc. Si la asignación falla, devuelven NULL. — Al liberar memoria, asigne el puntero a NULL para evitar el uso de un bloque liberado. — No use el puntero después de free. — Mantenga la correspondencia correcta entre malloc/free y calloc/free.
Ejemplo de código:
#include <stdio.h> #include <stdlib.h> int main() { int *arr = malloc(5 * sizeof(int)); if (!arr) { perror("No se pudo asignar memoria"); return 1; } for (int i = 0; i < 5; ++i) arr[i] = i * i; for (int i = 0; i < 5; ++i) printf("%d ", arr[i]); printf(" "); free(arr); arr = NULL; return 0; }
Características clave:
¿Qué sucede al liberar memoria asignada a través de malloc con el operador delete o viceversa (en C++)?
No se pueden mezclar los mecanismos de asignación y liberación de memoria entre lenguajes (C/C++). En C — solo malloc/free, en C++ — new/delete.
¿Qué sucede al intentar llamar a free(NULL)?
free(NULL) — es seguro (esto está garantizado por el estándar de C). Tal llamada no hace nada.
¿Se puede usar realloc para aumentar o disminuir un bloque de memoria y qué sucede con el puntero original?
realloc puede mover el bloque de memoria, y si esto ocurre, el puntero antiguo se vuelve inválido. Siempre asigne el nuevo puntero:
ptr = realloc(ptr, new_size);
Se asignó memoria para un arreglo en un bucle, pero se olvidó liberar al final de la iteración. Durante la noche, el programa "consumió" toda la RAM del servidor.
Ventajas:
Desventajas:
En el bucle, siempre se liberaba la memoria después de su uso, todas las comprobaciones de NULL se hacían justo después de malloc, se utilizaron herramientas de depuración para controlar las fugas.
Ventajas:
Desventajas: