malloc和free实现分析
函数原型
#include <stdlib.h>
/*
 * 分配一块指定大小的、未初始化的连续内存
 * sz: 想要分配的字节数
 * 返回值:
 *  成功时,返回指向新分配内存块的首地址
 *  失败时,返回NULL
 */
void *malloc (size_t sz);
/*
 * 分配指定数量个,长度为指定大小的、清零的连续内存
 * num: 想要分配的元素数量
 * sz: 每个元素的大小(以字节为单位)
 * 返回值:
 *  成功时,返回指向新分配内存块的首地址
 *  失败时,返回NULL
 */
void *calloc (size_t num, size_t sz)
/*
 * 调整先前由malloc、calloc或realloc分配的内存块的大小
 * ptr: 指向先前分配的内存块的指针。如果ptr为NULL,realloc的行为与malloc相同
 * sz: 新的内存块大小(以字节为单位)
 * 返回值:
 *  成功时,返回指向新分配内存块的首地址,新的内存块上会保留原始内存中的值,但是新增加的部分是未初始化的(可能会原地调整,首地址不变)
 *  失败时,返回NULL,并且原始内存块没有被释放
 */
void *realloc (void *ptr, size_t sz)
// 释放由malloc、calloc或realloc分配的内存
void free (void *ptr)
linux地址空间
Linux进程地址空间是指每个进程在运行时所能看到的虚拟内存空间。它是一个抽象概念。
这个虚拟地址空间不是实际的物理内存,而是由操作系统和硬件(MMU, 内存管理单元)共同管理的一种映射。
进程看到的地址是虚拟地址,当它需要访问某个地址时,操作系统会将其翻译成实际的物理地址。
                            高地址
                            +---------------------------+
                            |                           |
                            |     Kernel Space          |
                            |                           |
                            +---------------------------+
                            |                           |
                            |        Stack    ↓         |
                            |                           |
                            +---------------------------+
                            |                           |
                            |  Memory Mapping Segment ↓ |
                            |                           |
                            +---------------------------+
                            |                           |
                            |         Heap    ↑         |
                            |                           |
                            +---------------------------+
                            |                           |
                            |     BSS Segment           |
                            |                           |
                            +---------------------------+
                            |                           |
                            |     Data Segment          |
                            |                           |
                            +---------------------------+
                            |                           |
                            |     Text Segment          |
                            |                           |
                            +---------------------------+
                            低地址
一个典型的Linux进程地址空间从高到低通常包含以下几个区域:
- 内核空间:运行操作系统内核的代码。所有进程共享这部分空间,但用户程序无法直接访问。
- 用户空间:每个进程独享这部分空间。
    - 栈: 存放局部变量、函数参数和函数返回地址。栈从高地址向低地址增长。
- 内存映射段: 用于动态加载共享库(如 libc.so)和通过mmap()映射的文件。
- 堆: 用于动态内存分配,比如使用malloc()或 new 分配的内存。堆从低地址向高地址增长。
- BSS段: 存放未初始化的全局变量和静态变量。在程序加载时,这部分内存会被自动清零。
- 数据段: 存放已初始化的全局变量和静态变量。
- 代码段: 存放程序的可执行代码以及常量数据。这部分内存通常是只读的,以防止代码被意外修改。
 
内核空间 (Kernel Space):
malloc原理
ptmalloc是glibc中的malloc实现。