《Linux/Unix系统编程手册》内存分配

动态内存的底层表示

当我们使用mallocfree函数在内存中开辟新内存的时候,我们究竟是改变了什么呢?其实在内存中有一个program break,这个玩意儿是堆的边界。如果有新的内存被开辟了,这个指针_可能_会移动。

开辟内存的函数

最底层的函数

首先是最底层的两个函数:

1
2
int brk(void* end_data_segment);
void* sbrk(intptr_t increment);

brk()函数会将program break的位置设置为参数的位置,从而自动开辟内存。

sbrk()函数需要指定一个偏移量,program break的位置会跟随这个偏移量偏移。

C函数

mallocfree

C的函数就是mallocfree了。但是我们还是得了解一下这两个函数的工作原理:

首先malloc首先按会扫描program break内空白的部分,如果空白的部分大于分配内存,那么就将空白部分切片并且返回分配内存的内存地址;如果刚好合适就返回内存地址;如果没有合适大小的内存就移动program break来扩大堆大小。需要注意的是:

  • 其不仅会分配内存,还会在内存的前几个字节的地方记录分配内存的大小。
  • 扩大堆的大小是按照页的大小来的,而不是按照分配内存大小来的(多分配一点防止下次还要分配)

内存分配

free函数的做法则是这样:

首先free函数有一个空闲列表来以链表的方式存放空闲的内存(放在本身空闲的内存中),当调用free的时候会在列表中查找以便快速找到要删除的内存。

其他函数

其他函数还有calloc(), realloc()

注意alloc()函数的用法虽然和malloc()很像,但是却不是在堆上分配的内存,而是通过增加帧栈的方式在堆栈上分配内存。所以使用alloc()函数分配的内存不能够(也不应该)使用free()函数消除。由于是在帧栈上分配内存,所以你不应该使用alloc()函数分配全局变量。

alloc分配内存比较快,而且其分配的内存可以随着帧栈的移除而自动释放。

alloc函数在alloca.h头文件中

updatedupdated2023-06-182023-06-18