Double Free or Corruption Error in C++

Muhammad Husnain 12 Oktober 2023
  1. Dynamische Speicherzuweisung und -freigabe in C++
  2. double free or corruption Fehler in C++
  3. So vermeiden Sie den Fehler double free or corruption in C++
Double Free or Corruption Error in C++

In diesem Lernprogramm werden Probleme erörtert, die bei dynamischen Speicherzuweisungen in C++ auftreten. Bei der Verwendung von Heap-Speicher stoßen wir auf viele Probleme, die bei der Verwaltung von Heap-Speicher sehr wichtig sind.

Zuerst werden wir besprechen, wie wir Speicher zuweisen und die verschiedenen Methoden, die in C++ bereitgestellt werden; Anschließend werden wir uns mit den Ursachen und Lösungen des Fehlers double free or corruption in C++ befassen.

Dynamische Speicherzuweisung und -freigabe in C++

C++ ermöglicht es uns, während der Laufzeit Variablen- oder Array-Speicher zuzuweisen. Dies wird als dynamische Speicherzuordnung bezeichnet.

In anderen Programmiersprachen wie Java und Python verwaltet der Compiler den Variablenspeicher automatisch. Dies ist jedoch in C++ nicht der Fall.

In C++ müssen wir dynamisch zugewiesenen Speicher manuell freigeben, nachdem wir ihn nicht mehr benötigen. Mit den Funktionen new und delete können wir Speicher dynamisch zuweisen und freigeben.

Es gibt zwei weitere Funktionen, nämlich malloc und free, die ebenfalls in C++ für die dynamische Speicherzuweisung und -freigabe enthalten sind.

Betrachten Sie ein Beispiel unten, das die Verwendung der Funktionen new und delete demonstriert.

#include <iostream>
using namespace std;

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

Wir haben Speicher für eine int-Variable mit dem new-Operator dynamisch zugewiesen. Es ist erwähnenswert, dass wir die Referenzvariable ptr verwendet haben, um Speicher dynamisch zuzuweisen.

Der Operator new gibt die Adresse des Speicherplatzes zurück. Bei einem Array gibt der Operator new die Adresse des ersten Elements des Arrays zurück.

Wir können den Speicher freigeben, der von einer dynamisch deklarierten Variablen verwendet wird, nachdem wir ihn nicht mehr verwenden müssen. Dazu wird der Operator delete verwendet.

Es gibt den Speicher an das Betriebssystem zurück. Dies wird als Speicherfreigabe bezeichnet.

Das nächste Beispiel zeigt Ihnen eine Demonstration der Funktionen malloc und free.

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

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

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

In C++ weist die Methode malloc() einen Zeiger auf einen nicht initialisierten Speicherblock zu. Die Header-Datei cstdlib definiert es.

malloc übernimmt als Parameter die Speichergröße, die Sie zuweisen müssen, und gibt einen void-Zeiger zurück, der auf den zugewiesenen Speicherblock zeigt. Daher kann es gemäß unseren Anforderungen typisiert werden.

Andererseits gibt die Methode free() den Speicher frei, der mit der Funktion malloc zugewiesen wurde. Es gibt diesen Speicher an das Betriebssystem zurück und vermeidet Probleme mit Speicherlecks.

double free or corruption Fehler in C++

Double-Free-Fehler treten auf, wenn free() mehr als einmal mit derselben Speicheradresse als Eingabe verwendet wird.

Der zweimalige Aufruf von free() für dieselbe Variable kann zu einem Speicherleck führen. Wenn eine Software free() zweimal mit denselben Parametern ausführt, werden die Datenstrukturen der Speicherverwaltung in der Anwendung beschädigt, was es einem böswilligen Benutzer ermöglicht, Werte in jeden Speicherbereich zu schreiben.

Diese Beschädigung kann in einigen Fällen zum Absturz des Programms oder zu einer Änderung des Ausführungsablaufs führen. Ein Angreifer kann ein Programm dazu verleiten, einen Code seiner Wahl auszuführen, indem er bestimmte Register oder Speicherbereiche überschreibt, was zu einer interaktiven Shell mit erhöhten Rechten führt.

Eine verkettete Liste freier Puffer wird gelesen, wenn ein Puffer free() gemacht wird, um die Teile des freien Speichers neu zu organisieren und zu kombinieren (um in Zukunft größere Puffer zuzuweisen). Diese Chunks sind in einer doppelt verknüpften Liste mit Links zu den Chunks davor und danach organisiert.

Ein Angreifer könnte beliebige Werte in den Speicher schreiben, indem er die Verknüpfung eines unbenutzten Puffers aufhebt (was passiert, wenn free() aufgerufen wird), effektiv wertvolle Register überschreibt und Shellcode aus seinem Puffer startet.

Betrachten Sie ein Beispiel unten.

#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;
}

Ausgabe:

free(): double free detected in cache 2
Aborted

Im obigen Code-Snippet haben wir die Funktion free() zweimal verwendet, was bedeutet, dass wir versuchen, den bereits freien und nicht mehr zugewiesenen Speicher freizugeben. Dies führt zu einem Speicherleckproblem und ist die Hauptursache für den Absturz des Codes.

Es gibt auch viele andere Situationen, in denen solche Fehler auftreten können. Aber es gibt drei häufige (und sich oft überschneidende) Gründe für Double-Free-Schwachstellen.

  1. Fehlerzustände und andere ungewöhnliche Situationen
  2. Nachdem der Speicherplatz freigegeben wurde, wird er verwendet.
  3. Verwirrung darüber, welcher Abschnitt des Programms für die Speicherfreigabe zuständig ist

Obwohl einige Double-Free-Schwachstellen nicht viel komplexer sind als das vorhergehende Beispiel, sind die meisten von ihnen über Hunderte von Codezeilen oder sogar mehrere Dateien verteilt. Programmierer scheinen besonders anfällig dafür zu sein, globale Variablen mehrfach freizugeben.

So vermeiden Sie den Fehler double free or corruption in C++

Diese Art von Schwachstelle kann vermieden werden, indem unserem Zeiger immer dann NULL zugewiesen wird, wenn er frei wird (d. h. der Speicher, auf den dieser Zeiger zeigt, wird frei). Danach ignorieren die meisten Heap-Manager die freien Nullzeiger.

Es wird empfohlen, alle gelöschten Zeiger zu nullen und zu prüfen, ob die Referenz null ist oder nicht, bevor sie freigegeben wird. Am Anfang unseres Codes müssen wir den null-Zeiger initialisieren, bevor wir diesen Zeiger in jedem Fall verwenden.

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

Verwandter Artikel - C++ Error