linux在指定堆上分配内存,Linux当中内存分配

在堆上分配内存进程可以通过增加堆的大小来分配内存,所谓堆,就是一段长度可以变的连续虚拟内存,始于进程的未初始化数据末尾。通常将堆的当前内存边界称为program break

改变堆的大小,其实就像命令内核改变进程的program break位置一样,program break位置抬升后,程序可以访问新分配区域的任何内存地址,而此时物理内存页尚未分配。内核会在进程首次试图访问这些虚拟内存地址的时候,自动分配新的物理页内存

点击(此处)折叠或打开

#include

/*将program break设置为参数end_data_segment所指定的位置,四舍五入到下一个内存页的边界处*/

int brk(void *end_data_segment);

/*returns 0 on success, or -1 on error*/

/*将program break 在原有地址上增加从参数increment传入的大小*/

void *sbrk(intptr_t increment);//sbrk(0)返回当前program break的当前位置

/*returns previous program break on success, or (void *)-1 on error*/

点击(此处)折叠或打开

#include

void *malloc(size_t size);// memory aligned

/*returns pointer to allocated memory on success, or NULL on error*/

void free(void *ptr);// ptr can be NULL一般情况下,free()并不降低program break的位置,而是将这块内存添加到空闲内存链表中,供后续的malloc()函数循环使用,除非释放的部分位于program break当前的位置且足够大时,才会降低program break

malloc()实现

首先,malloc()在分配内存块的时候,会额外分配几个自己来存放记录这块内存大小的整数值。该整数位于内存块的起始处,而实际返回给调用者的内存地址恰好位于这一长度记录字节字后

先臊面之前有free()所释放的空闲内存块列表,以求能够找到尺寸大于或等于要求的一块空闲内存。若大,进行分割,返回合适大小,将剩余加入空闲列表

如果空闲列表中没有合适大小的空闲块,调用sbrk()以分配更多的内存,为了减少对sbrk()的调用次数,malloc()并没有严格按照所需字节来分配内存,而是以更大幅度(虚拟页大小的倍数)来增加program break,并将超出的部分置于空闲内存列表free()实现

当free()将内存块置于空闲链表之上时,会使用内存块本身的空间来存放两个(prev和next)链表指针,将自身添加到列表中glibc提供的malloc()调试工具

mtrace(), muntrace()

分别在程序中打开和关闭对内存分配调用进行跟踪的功能。这些函数要与环境变量MALLOC_TRACE搭配使用,该变量定义了写入跟踪信息的文件名。还提供一个脚本(mtrace)用于分析生成文件,并生成易于理解的汇总报告。出于安全原因,设置用户id和组id的程序会忽略对于mtrace()的调用mcheck(), mprobe()

允许程序对已分配内存进行一致性检查。例如,当程序视图在已经分配的内存之外进行写操作时,它会捕获这个错误。使用这些函数的程序,必须使用cc -lmcheck 选项与mcheck库链接MALLOC_CHECK_环境变量

提供了类似于mcheck(), mprobe()函数的功能。通过对其设置不同的值,可以控制程序对内存分配错误的相应方式:0->忽略;1->标准错误打印;2->调用abort()异常终止

valgrind和insure++ 能够发现许多堆内存分配之外的其他类型错误

点击(此处)折叠或打开

#include

//参数分别表示分配对象的数量,和每个对象的大小, 会将内存初始化为0

void *calloc(size_t numitems, size_t size);

/*returns pointer to allocated memory on success, or NULL on error*/

点击(此处)折叠或打开

#include

void *realloc(void *ptr, size_t size);

/*returns pointer to allocated memory on */参数ptr指向需要调整大小的内存块的指针,参数size指定所需要调整大小的期望值

点击(此处)折叠或打开

nptr = realloc(ptr, newsize);

if(nptr == NULL){

/*handle error*/

}else{

ptr = nptr;//这里不用ptr直接接受返回值就是为了防止出错的时候,仍旧可以对原内存块进行操作

}分配堆砌的没存:memalign()和posix_memalign()

点击(此处)折叠或打开

#include

void *memalign(size_t boundary, size_t size);

/*returns pointer to allocated memory on success, or NULL on error*/

memalign()分配size个字节的内存,起始地址是参数boundary的整数倍,而boundary必须是2的整数次幂。

点击(此处)折叠或打开

#include

int posix_memalign(void **memptr, size_t alignment, size_t size);

/*returns 0 on success, or a positive error number on error*/其分配内存地址通过参数memptr返回,内存块的起始地址是alignment参数的整数倍,alignment必须是sizeof(void *)与2的整数次幂两者之间的乘积

点击(此处)折叠或打开

int s;

void *memptr;

s = posix_memalign(&memptr, 1024 * sizeof(void *), 65536);

if(s!=0)

/*handle error*/

在堆栈上分配内存

点击(此处)折叠或打开

#include

void *alloca(size_t size);

/*returns pointer to allocated block of memory*/alloca()是通过增加栈帧的大小从堆栈上分配内存的,当前调用函数的栈帧位于堆栈的顶部。不需要用free()来释放alloca()分配的内存,也不能调用realloc()调整alloca()分配的内存。不能在一个函数的参数列表中调用alloca(),必须采用如下代码:

点击(此处)折叠或打开

void *y;

y = alloca(size);

func(x, y, z);alloca()相比于malloc()函数族的优势在于分配快速,编译器会将其当做内联代码处理,并通过调整堆栈指针来实现,不需要维护空闲内存块的链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值