内存分配器一

5 篇文章 0 订阅
3 篇文章 0 订阅

glibc内存管理学习
http://www.cnblogs.com/tianchi/archive/2012/08/02/2620634.html
x86平台Linux进程内存布局:
text:ELF格式程序代码
data:程序运行时就能确定的数据,可读可写
bss:没有初始化的全局变量和静态表里
heap
stack:由编译器自动分配释放,存放函数参数、局部变量等
Mmap:映射区域
实现一个malloc
http://blog.jobbole.com/75656/
分页与地址
现代操作系统中,不论是虚拟内存还是物理内存,都不是以字节为单位进行管理的,而是以页(page)为单位。一般内存页的大小为4k(4096Byte),需要12位的地址,内存地址是以页号加一个12位的偏移组成。

实现malloc
void * malloc(size_t size)
函数的主要功能是分配大小至少为size参数所指定的字节数并返回一个一个指针指向该内存地址的首地址
实现参照http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf
首先简单实现函数:
IMalloc.h:

#ifndef IMALLOC_H
#define IMALLOC_H
#include<unistd.h>
#include<sys/types.h>
void *Imalloc(size_t size);
#endif`

IMalloc.c:

#include"IMalloc.h"
void *Imalloc(size_t size)
{
    void *p;
    p=sbrk(0);
    if(sbrk(size)==(void*)-1)       
        return NULL;
    return p;   
}

其中函数
void *sbrk(intptr_t increment);
是用来获取Heap区域的break点,由于受物理存储量的限制,整个堆虚拟内存空间不可能全部映射到实际物理内存地址中。从堆起始地址到break之间的地址空间为映射好的,可以供进程访问;而从break往上,是未映射的地址空间,如果访问这段空间则程序会报错。
main.c:

#include"IMalloc.h"
int main(void)
{
    int *p=(int*)Imalloc(sizeof(int)*2);
    int *pp=(int*)Imalloc(sizeof(int)*1);
    void *cur=sbrk(0);
    p[0]=1;
    p[1]=2;
    p[2]=3;
    pp[0]=4;
    pp[1]=5;
    pp[2]=5;
    pp[1028]=10;
    return 0;
}

编译链接可以在gdb中调试:
gcc -g main.c IMalloc.c -o main
(gdb) main
(gdb) start

然后执行到
(gdb) n
10 p[2]=3;

可以查看内存如下,p[0]和p[1]中的值为1和2
(gdb) x/8a p
0x804b000: 0x1 0x2 0x0 0x0
0x804b010: 0x0 0x0 0x0 0x0

越界操作,修改了p[2]地址中的值
(gdb) n
11 pp[0]=4;
(gdb) x/8a p
0x804b000: 0x1 0x2 0x3 0x0
0x804b010: 0x0 0x0 0x0 0x0

然后执行将值修改回来
(gdb) n
12 pp[1]=5;
(gdb) x/8a p
0x804b000: 0x1 0x2 0x4 0x0
0x804b010: 0x0 0x0 0x0 0x

当执行到pp[1028]=10这段代码之前,可以修改当前heap的break后面内存的值。
(gdb) n
14 pp[1028]=10;
(gdb) x/8a p
0x804b000: 0x1 0x2 0x4 0x5
0x804b010: 0x5 0x0 0x0 0x0

当前break指向的地址为如下所示,在pp[2]之前
(gdb) display cur
1: cur = (void *) 0x804b00c

但是当我们访问超出一页内存(4k)时,会报错
Program received signal SIGSEGV, Segmentation fault.
0x080484a7 in main () at main.c:14
14 pp[1028]=10;

说明了一点heap上面映射的区域是一页一页映射的,当访问当前break之后的一页的内存时会出错。
当修改代码为如下时,则可以正常执行。

int *pp=(int*)Imalloc(sizeof(int)*1028);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值