迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C++ >

C++ 中的双重释放或损坏错误

作者:迹忆客 最近更新:2023/03/23 浏览次数:

本文将讨论 C++ 中动态内存分配中出现的问题。在使用堆内存时,我们会遇到许多在进行堆内存管理时非常重要的问题。

首先,我们将讨论如何分配内存以及 C++ 中提供的不同方法;然后,我们将探讨 C++ 中出现 double free or corruption 错误的原因和解决方案。

C++ 中的动态内存分配和释放

C++ 允许我们在运行时分配变量或数组内存。这称为动态内存分配。

在其他编程语言中,例如 Java 和 Python,编译器会自动维护变量内存。但是,在 C++ 中并非如此。

在 C++ 中,我们必须在不再需要动态分配的内存后手动释放它。我们可以使用 newdelete 函数动态分配和释放内存。

还有另外两个函数,即 mallocfree,它们也包含在 C++ 中,用于动态内存分配和释放。

参考下面的示例,演示 newdelete 函数的使用。

#include <iostream>
using namespace std;

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

我们使用’new’操作符为一个 int 变量动态分配内存。值得注意的是,我们使用了引用变量 ptr 来动态分配内存。

new 运算符返回内存位置的地址。在数组的情况下,new 运算符返回数组第一个元素的地址。

在我们不再需要使用动态声明的变量后,我们可以释放它所使用的内存。delete 运算符用于此目的。

它将内存返回给操作系统。这称为内存释放。

下一个示例将向你展示 mallocfree 函数的演示。

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

int main() {

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

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

在 C++ 中,malloc() 方法分配一个指向未初始化内存块的指针。cstdlib 头文件定义它。

malloc 将需要分配的内存大小作为参数,并返回一个指向已分配内存块的 void 指针。因此可以根据我们的要求进行类型转换。

另一方面,free() 方法释放使用 malloc 函数分配的内存。它将内存返回给操作系统并避免内存泄漏问题。

C++ 中的双重释放或损坏错误

当多次使用 free() 且内存地址作为输入时,会发生双重释放错误。

在同一个变量上调用 free() 两次可能会导致内存泄漏。当软件使用相同的参数运行两次 free() 时,应用程序中的内存管理数据结构会损坏,从而允许恶意用户在任何内存区域中写入值。

在某些情况下,这种损坏可能导致程序崩溃或更改执行流程。攻击者可以通过覆盖特定的寄存器或内存区域来误导程序执行他们选择的代码,从而产生具有提升权限的交互式 shell。

当缓冲区被 free() 重新组织和组合空闲内存块(以在将来分配更大的缓冲区)时,将读取空闲缓冲区的链接列表。这些块被组织在一个双链表中,其中包含指向它们之前和之后的块的链接。

攻击者可能通过断开未使用的缓冲区(在调用 free() 时发生)、有效地覆盖有价值的寄存器并从其缓冲区启动 shellcode 来在内存中写入任意值。

参考下面的一个例子。

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

int main() {

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

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

输出:

free(): double free detected in cache 2
Aborted

在上面的代码片段中,我们两次使用了 free() 函数,这意味着我们正在尝试释放已经空闲且不再分配的内存。这会产生内存泄漏问题,并且是导致代码崩溃的根本原因。

还有许多其他情况可能会遇到此类错误。但是双重释放漏洞有三个常见(并且经常重叠)的原因。

  1. 错误情况和其他异常情况
    2、内存空间释放后,使用。
  2. 不清楚程序的哪个部分负责内存释放

虽然一些双重释放漏洞并不比前面的例子复杂多少,但它们大多分布在数百行代码甚至多个文件中。程序员似乎特别容易多次释放全局变量。

如何避免 C++ 中的双重释放或损坏错误

这种类型的漏洞可以通过在指针空闲时将其分配给 NULL 来避免(即,该指针指向的内存空闲)。之后,大多数堆管理器都会忽略空闲的空指针。

建议将所有已删除的指针置空,并在释放它之前检查引用是否为 null。在我们的代码开始处,我们必须在任何情况下使用该指针之前初始化 null 指针。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Arduino 中停止循环

发布时间:2024/03/13 浏览次数:444 分类:C++

可以使用 exit(0),无限循环和 Sleep_n0m1 库在 Arduino 中停止循环。

Arduino 复位

发布时间:2024/03/13 浏览次数:315 分类:C++

可以通过使用复位按钮,Softwarereset 库和 Adafruit SleepyDog 库来复位 Arduino。

Arduino 的字符转换为整型

发布时间:2024/03/13 浏览次数:181 分类:C++

可以使用简单的方法 toInt()函数和 Serial.parseInt()函数将 char 转换为 int。

Arduino 串口打印多个变量

发布时间:2024/03/13 浏览次数:381 分类:C++

可以使用 Serial.print()和 Serial.println()函数在串口监视器上显示变量值。

Arduino if 语句

发布时间:2024/03/13 浏览次数:123 分类:C++

可以使用 if 语句检查 Arduino 中的不同条件。

Arduino ICSP

发布时间:2024/03/13 浏览次数:214 分类:C++

ICSP 引脚用于两个 Arduino 之间的通信以及对 Arduino 引导加载程序进行编程。

使用 C++ 编程 Arduino

发布时间:2024/03/13 浏览次数:127 分类:C++

本教程将讨论使用 Arduino IDE 在 C++ 中对 Arduino 进行编程。

Arduino 中的子程序

发布时间:2024/03/13 浏览次数:168 分类:C++

可以通过在 Arduino 中声明函数来处理子程序。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便