堆基本概念
本文最后更新于28 天前,其中的信息可能已经过时,如有错误请发送邮件到506742773@qq.com

前言

看雪的笔记,希望对你有帮助,我也学到了不少东西

ptmalloc2是目前linux标准发行版中使用的堆分配器

内存分配思想

  • 堆管理器负责向操作系统申请内存,然后将其返回给用户程序,但是频繁的系统调用会

造成大量的开销。为了保持内存管理的高效性,内核一般都会预先分配很大的一块连续

的内存,然后让堆管理器通过某种算法管理这块内存。只有当出现了堆空间不足的情

况,堆管理器才会再次与操作系统进行交互。

  • 一般来说,用户释放的内存并不是直接返还给操作系统的,而是由堆管理器进行管理。

这些释放的内存可以来响应用户新申请的内存的请求。

堆基本操作

malloc

malloc(memoryallocation)函数是c语言标准库中用于动态内存分配的一个基本函数。它分配一块至少为size字节的连续内存区域,并返回一个指向这块内存的指针

void *malloc(size_t size);

malloc函数返回对应大小字节的内存块的指针。此外,该函数还对一些异常情况进行了处理:

  • 当n=0时,返回当前系统允许的堆的最小内存块
  • 当为负数时,由于在大多数系统上,size_t是无符号数(这一点非常重要),所以程序就会申请很大的内存空间,但通常来说都会失败,因为系统没有那么多的内存可以分配。

realloc

realloc函数用于重新分配之前通过malloc,calloc或realloc函数分配的内存区域。它可以改变内存块的大小,或者释放内存块,或分配新的内存块。

void *realloc(void*ptr,size_t size);
  • ptr:指向需要重新分配的内存块的指针。
  • size:新的内存块的大小,以字节为单位。

有如下情况:

  • ptr不为空,size=0,相当于释放原来的堆块。
  • ptr为空且size>0,相当于malloc。
  • ptr不为空,size大于原来的堆块大小则如果该堆块后面的堆块空闲则合并堆块,否则

先释放原堆块,然后再申请一个更大的堆块,原堆块内容会被拷贝过去。

  • ptr不为空,size不大于原来的堆块大小,如果切割后剩下的堆块大于等于MINSIZE

则切割并释放,然后返回原堆块。

calloc

calloc(contiguousallocation)函数是c语言标准库中用于动态内存分配的一个函数。与malloc相似,calloc用于分配内存。该函数在分配时会清空chunk上的内容,这使得我们无法通过以往的重复存取后通过chunk上残留的脏数据的方式泄露信息(例如通过bins数组遗留的脏数据泄露libc基址等),同时该函数不从tcache中拿chunk,但是free函数默认还是会先往tcache里放的,这无疑增加了我们利用的难度。

void *calloc(size_t nmemb, size_t size);
  • nmemb:需要分配的元素个数。
  • size:每个元素的大小,以字节为单位。
  • 总的分配的字节大小是nmemb*size。

注意:如果size的IS_MAPPED位置1则不清空数据。

if (chunk_is_mmapped (p))
{
if(_builtin_expect (perturb_byte,0))
return memset (mem, O, sz);
return mem;
}

修改堆中的字段进行利用,暂不做阐述

free

free函数会释放由p所指向的内存块。这个内存块有可能是通过malloc函数得到的,也有可能是通过相关的函数realloc得到的。

异常情况处理:

  • 当p为空指针时,函数不执行任何操作。
  • 当p已经被释放之后,再次释放会出现乱七八糟的效果,doublefree。
  • 除了被禁用(mallopt)的情况下,当释放很大的内存空间时,程序会将这些内存空间还给系统,以便于减小程序所使用的内存空间。

mallopt

mallopt函数通过控制堆的特定参数用于改变堆的分配策略。

int mallopt(int param,int value)

param:指定要修改的动态内存分配参数。这个参数是一个整数,定义了哪一个特性将会被修改。例如,它可以是控制内存对齐、缓存大小或者相似行为的选项。

  • M_MXFAST:设置malloc用于小块内存分配的最大fast bin的大小。
  • M_TRIM_THRESHOLD:设置sbrk释放内存回操作系统的阈值。
  • M_TOP_PAD:设置sbrk请求额外内存时,上面的额外内存量。
  • M_MMAP_THRESHOLD:设置使用mmap进行内存分配的阈值。
  • M_MMAP_MAX:设置可以使用mmap进行内存分配的最大数目。

value:新的值,针对param指定的特性。具体的值取决于param,有些特性可能需要非零值来启用,零值来禁用,有些则需要具体的数值。

返回值是一个整数,指示函数调用是否成功。

  • 如果成功,返回非零值。
  • 如果失败(例如,不支持的参数或值),返回零。

内存分配背后的系统调用

内存管理函数背后的系统调用主要是 (s)brk 函数以及 mmap, munmap 函数。
在 main arena 中通过 sbrk 扩展 heap,而在 thread arena 中通过 mmap 分配新的 heap。

(s)brk

对于堆的操作,操作系统提供了 brk 函数,glibc 库提供了 sbrk 函数,我们可以通过增加 brk 的大小来向操作系统申请内存。

初始时,堆的起始地址 start_brk 以及堆的当前末尾 brk 指向同一地址。根据是否开启 ASLR,两者的具体位置会有所不同

不开启 ASLR 保护时,start_brk 以及 brk 会指向 data/bss 段的结尾。
开启 ASLR 保护时,start_brk 以及 brk 也会指向同一位置,只是这个位置是在 data/bss 段结尾后的随机偏移处。

mmap

malloc 会使用 mmap 来创建独立的匿名映射段。匿名映射的目的主要是可以申请以 0 填充的内存,并且这块内存仅被调用进程所使用。

加油啊,呜呜呜...
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇