堆块知识补充

本文详细介绍了堆管理器的工作原理,特别是Linux平台上的ptmalloc机制,包括chunk、bin的概念,malloc和free函数的用法,以及内存管理中的注意事项,如内存泄漏、悬垂指针和碎片化问题。
摘要由CSDN通过智能技术生成
一,堆管理器

在程序运行的过程中,堆可以提供动态分配的内存,从而允许程序申请大小未知的内左 堆其实就是程序虚拟地址空间的一块连续的线性区域,它由低地址向高地址方向增长,这和栈是相反的(栈是由高地址向低地址方向生长)。我们一般称管理堆的程序为堆管理器。

每个系统都有自己的堆管理器,堆利用就是针对堆管理器的一种利用思路。这是一种中介”的思想, 比如现实中,你要购买一套房子,你可以告诉中介你对房子的需求,如面积、地段、学区等,中介给你推荐适合的房子;当你想卖掉房子时,可以告诉中介房子的基本信息、出售价格等, 中介帮你寻找买家。堆也是这样,为了避免系统与用户频繁交互(因为和操作系统交互非常耗时),就有了堆管理器。实际上,用户平时申请(malloc)和释放free) 堆块的时候,是和堆管理器直接接触的。

不同平台的堆管理器是不一样的,比如 Windows、 Linux、 Mac的处理机制不一样,用请求堆块和释放堆块的流程也不一样。在本书中,我们主要研究 Linux平台上的 ptmalloc 机制。以及在ptmalloc 机制上的利用。

二,ptmalloc堆管理器的基本功能

堆管理器处于用户和内核之间,主要负责完成用户的两个需求:malloc(申请堆块) 和 (释放堆块)

 一般来说,用户不管是请求堆块还是释放堆块,都不是直接和操作系统打交道,而是和堆管理器打交道。当用户请求一个堆块时,堆管理器需要响应用户的申请内存请求,并且向操作系统申请内存,然后将这个堆块返回给用户程序。这种响应的逻辑对应每个堆管理器的算法,在ptmalloc堆管理器中,内核一般会预先分配一块很大的连续的内存然后让堆管理器通过某种算法管理这块内存,只有当出现堆空间不足的情况时,ptmalloc堆管理器才会再次与操作系统进行交互,通过系统调用申请内存。释放堆块的时候也是一样,ptmalloc堆管理器需要管理用户释放的堆块。在 ptmalloc中,会通过一系列的 bin进行管理。值得一提的是,用户请求的堆块不仅来自系统分配的堆块,也可能来自这些堆管理器管理的释放之后的堆块。

□chunk: 在ptmalloc中, 堆管理器会利用malloc chunk结构体管理所有的堆块,所以我们将堆管理器中出现的堆块叫作 chunk,而将在程序中直接使用的内存块称为堆(heap)。

□free:也叫作释放,即在程序中调用 free 函数释放这个堆块。

□bin: 在ptmalloc中用来保存没有使用的 chunk(释放之后的 chunk)。根据需求的不同,bin在数据结构上表现为单向链表或者双向循环链表。

三,malloc和free
malloc是用户程序申请堆块的常用函数

我们可以了解 malloc函数的一些基本信息:

malloc(memory allocate)函数用于在堆上分配指定大小的内存块。它返回一个指向新分配内存的指针,如果分配失败则返回 NULL

void *malloc(size_t size);
  • size 参数指定了要分配的字节数。
int *ptr = (int *)malloc(sizeof(int) * 10);
if (ptr == NULL) {
// 内存分配失败,处理错误
} else {
// 使用分配的内存
}

在这个例子中,我们分配了一个能够存储10个整数的内存块,并将返回的指针转换为 int * 类型。如果没有空间可用, 会返回 null(0)。如果malloc 函数的参数是 0, 会返回一个最小的 chunk。如果malloc函数的参数是一个负数,那么会申请一个很大的空间。但一般来说,这么大的空间是不会申请成功的,所以会返回null(0)。

free是用户程序释放一个堆块时常用的函数

free 函数用于释放之前通过 malloccalloc 或 realloc 分配的内存块。释放内存后,相应的指针应被设置为 NULL,以防止成为“悬垂指针”(dangling pointer)。

void free(void *ptr);
  • ptr 参数是一个指向要释放的内存块的指针。
int *ptr = (int *)malloc(sizeof(int) * 10);
if (ptr != NULL) {
// 使用分配的内存
// ...
// 释放内存
free(ptr);
ptr = NULL; // 防止悬垂指针
}

 

注意事项
  1. 内存泄漏:如果分配的内存没有被释放(即忘记调用 free),则会导致内存泄漏。这会导致程序占用的内存不断增加,最终可能导致系统资源耗尽。
  2. 悬垂指针:释放内存后,原来的指针仍然指向已经被释放的内存块。这种指针被称为悬垂指针。访问悬垂指针是危险的,因为它可能导致不可预测的行为,包括程序崩溃。因此,释放内存后,应将指针设置为 NULL
  3. 多次释放:尝试释放同一块内存多次(即多次调用 free)也是错误的。这可能导致不可预测的行为,包括程序崩溃。
  4. 内存对齐和碎片化:频繁地分配和释放小块内存可能会导致内存碎片化,降低内存使用效率。此外,某些硬件平台对内存对齐有要求,如果分配的内存没有正确对齐,可能会导致性能下降或硬件异常。

因此,在使用 malloc 和 free 时,需要谨慎处理内存分配和释放,以确保程序的正确性和稳定性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值