Error double free or corruption en C++

Muhammad Husnain 12 octubre 2023
  1. Asignación y desasignación de memoria dinámica en C++
  2. Error de double free or corruption en C++
  3. Cómo evitar el error double free or corruption en C++
Error double free or corruption en C++

Este tutorial discutirá los problemas que ocurren en las asignaciones de memoria dinámica en C++. Cuando usamos la memoria en montón, nos encontramos con muchos problemas que es muy importante abordar al administrar la memoria en montón.

Primero, discutiremos cómo asignamos la memoria y los diferentes métodos provistos en C++; luego, avanzaremos hacia las causas y soluciones del error double free or corruption en C++.

Asignación y desasignación de memoria dinámica en C++

C++ nos permite asignar memoria de matriz o variable durante el tiempo de ejecución. Esto se conoce como asignación de memoria dinámica.

En otros lenguajes de programación, como Java y Python, el compilador mantiene la memoria variable automáticamente. Sin embargo, este no es el caso en C++.

En C++, debemos desasignar manualmente la memoria asignada dinámicamente después de que ya no la necesitemos. Podemos asignar y desasignar memoria dinámicamente usando las funciones new y delete.

Hay otras dos funciones, es decir, malloc y free, que también se incluyen en C++ para la asignación y desasignación de memoria dinámica.

Considere un ejemplo a continuación que demuestra el uso de las funciones new y delete.

#include <iostream>
using namespace std;

int main() {
  int* ptr;
  ptr = new int;
  *ptr = 40;
  cout << *ptr;
  delete ptr;
  return 0;
}

Asignamos memoria dinámicamente para una variable int usando el operador ’nuevo’. Vale la pena señalar que usamos la variable de referencia ptr para asignar memoria dinámicamente.

El operador new devuelve la dirección de la ubicación de memoria. En el caso de una matriz, el operador new devuelve la dirección del primer elemento del array.

Podemos desasignar la memoria utilizada por una variable declarada dinámicamente después de que ya no necesitemos utilizarla. Para ello se utiliza el operador delete.

Devuelve la memoria al sistema operativo. Esto se conoce como desasignación de memoria.

El siguiente ejemplo le mostrará una demostración de las funciones malloc y free.

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

int main() {
  int* ptr2 = (int*)malloc(sizeof(int));
  *ptr2 = 50;

  cout << *ptr2;
  free(ptr2);
  return 0;
}

En C++, el método malloc() asigna un puntero a un bloque de memoria sin inicializar. El archivo de cabecera cstdlib lo define.

malloc toma como parámetro el tamaño de la memoria que necesita asignar y devuelve un puntero vacío que apunta al bloque de memoria asignado. Por lo tanto, se puede encasillar de acuerdo con nuestros requisitos.

Por otro lado, el método free() desasigna la memoria asignada mediante la función malloc. Devuelve esa memoria al sistema operativo y evita problemas de pérdida de memoria.

Error de double free or corruption en C++

Los errores de doble libre ocurren cuando free() se usa más de una vez con la misma dirección de memoria como entrada.

Llamar a free() en la misma variable dos veces puede provocar una pérdida de memoria. Cuando un software ejecuta free() dos veces con el mismo parámetro, las estructuras de datos de administración de memoria en la aplicación se corrompen, lo que permite que un usuario malintencionado escriba valores en cualquier área de memoria.

Esta corrupción puede hacer que el programa se bloquee o cambie el flujo de ejecución en algunos casos. Un atacante puede engañar a un programa para que ejecute un código de su elección sobrescribiendo registros específicos o regiones de memoria, lo que da como resultado un shell interactivo con derechos elevados.

Una lista enlazada de búferes libres se lee cuando un búfer es libre() para reorganizar y combinar las piezas de memoria libre (para asignar búferes más grandes en el futuro). Estos fragmentos están organizados en una lista de enlaces dobles con enlaces a los fragmentos anteriores y posteriores.

Un atacante podría escribir valores arbitrarios en la memoria desvinculando un búfer no utilizado (lo que sucede cuando se invoca free()), sobrescribiendo registros valiosos y ejecutando shellcode desde su búfer.

Considere un ejemplo a continuación.

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

int main() {
  int* ptr2 = (int*)malloc(sizeof(int));
  *ptr2 = 50;

  cout << *ptr2;
  free(ptr2);
  free(ptr2);
  return 0;
}

Producción :

free(): double free detected in cache 2
Aborted

En el fragmento de código anterior, hemos usado la función free() dos veces, lo que significa que estamos tratando de liberar la memoria que ya está libre y que ya no está asignada. Esto crea un problema de fuga de memoria y es la causa raíz del bloqueo del código.

Hay muchas otras situaciones también que pueden encontrar este tipo de errores. Pero hay tres razones comunes (ya menudo superpuestas) para las vulnerabilidades sin dobles.

  1. Condiciones de error y otras situaciones inusuales
  2. Una vez liberado el espacio de la memoria, se utiliza.
  3. Confusión sobre qué sección del programa se encarga de liberar memoria

Aunque algunas vulnerabilidades sin dobles no son mucho más complejas que el ejemplo anterior, la mayoría de ellas se distribuyen en cientos de líneas de código o incluso en varios archivos. Los programadores parecen ser particularmente propensos a liberar variables globales varias veces.

Cómo evitar el error double free or corruption en C++

Este tipo de vulnerabilidad se puede evitar asignando NULL a nuestro puntero cada vez que se libera (es decir, la memoria a la que apunta este puntero se libera). Después de eso, la mayoría de los administradores de montones ignoran los punteros nulos gratuitos.

Se recomienda anular todos los punteros eliminados y comprobar si la referencia es nula o no antes de liberarla. Al comienzo de nuestro código, debemos inicializar el puntero null antes de usar ese puntero en cualquier caso.

Muhammad Husnain avatar Muhammad Husnain avatar

Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.

LinkedIn

Artículo relacionado - C++ Error