内存分配(持续更新)

1、brk释放内存和sbrk分配内存

#include<unistd.h>
int brk(void *end_data_segment);
成功返回0,否则为-1
将内存边界设置为参数所指定位置

void *sbrk(intptr_t increment);
成功返回之前的内存边界,失败返回(void*)-1
增加内存边界,返回为新分配内存的起始位置(sbrk(0)就是获得堆位置)

使用的例子

#include <iostream>
#include <unistd.h> 
using namespace std;
int main()
{
    int* phead; // 指向首位置
    int* pnow; // 指向当前指针位置
    pnow = sbrk(0); // 先分配空闲区域
    phead = pnow; // 固定首位置不变
    for(int i=2; i<10000; i++)
    {
        if(isPrime(i)) // 该函数用于判断是否是素数(忽略)
        {
           brk(pnow+1);// 分配4个字节(1个int)
            *pnow = i; // 存入数据
            pnow = sbrk(0); // 指向系统指针上次移动到的那个位置
        }
    }

    pnow = phead; // 从头打印
    while(pnow!=sbrk(0))
    {
        cout <<*pnow<<endl;
        pnow++;
    }
    brk(phead); // 释放空间
}

二、malloc和free使用

#include<stdlib.h>
void *malloc(size_t size);
成功返回分配的首地址,失败返回NULL

void free(void *ptr);

若无法分配内存,或者因为已经抵达内存边界所能达到的地址上限,则malloc返回NULL,所以一定要进行malloc返回值的错误检查。

free函数并不降低内存边界的位置,而是将这块内存添加到空闲的内存列表中,供后续的malloc循环使用。

说清楚点就是free并不是把栈的地址的内容给清零,而是告诉系统栈的某块内容可以被使用而已。如果够不告诉系统,则表明该区域一直在使用(实际上已经不使用了)。那么系统在做下一次new或者malloc的操作的时候就会开辟另一个空间。但是栈空间是有限的,如果一直没有free那么这个栈就会溢出。

注意:
如char pt=(char )malloc(10*sizeof(char));
需要free(p)才会释放空间。
如果free的参数不是当时malloc返回的地址,就会出现如图的错误(改了很久的bug 2333)
这里写图片描述

三、malloc和free的实现

出现上图改了很久之后,我就在想,为什么一定要free参数是malloc的返回值,查了系统编程之后看到一张图就明白很多了。
这里写图片描述
当malloc分配内存块的时候,会额外分配几个字节来存放记录这块内存大小的整数值。该整数位于内存块的起始处,而malloc返回的是内存块之后的位置(箭头的位置)。free就去查找这个内存头的具体信息,来进行对malloc数据的释放,所以free的参数一定要传对,不然free就会出现严重的错误!!!

四、calloc

#include<stdlib.h>
void *calloc(size_t numitems,size_t size);
成功返回创建的初始地址,并且初始化内存为0,失败返回NULL

char pt==(char )calloc(100, sizeof(char));
然后用calloc开辟的空间其内容会自动初始化为空,等于把该栈中使用的空间清零。也就是赋值’\0’。(因为是char,所以是\0)。也需要用free来对该空间进行释放

五、realloc

#include<stdlib.h>
void *realloc(void *ptr,size_t size);
成功返回指向大小调整后内存块的指针,失败返回NULL

注意:
①调用relloc(ptr,0)等效于在free(ptr)之后调用malloc(0)
②若ptr为NULL,则realloc(NULL,size)相当于调用malloc(size)
③realloc增加了已分配的内存块的大小,则不会对额外分配的字节进行初始化。
④如果原来内存块位于堆的顶部,那么realloc将对堆空间进行拓展。如果内存块位于堆的中部,且紧邻其后的空闲内存空间大小不足,realloc会分配一块新内存,将原来数据复制到新内存块中,占用大量cpu时间,不推荐使用!
⑤扩充内存之后,原来指向内存的指针都用可能不能用,最好使用加偏移量的方式重新定位

char pt=(char )malloc(10*sizeof(char));
realloc(pt, 1000*sizeof(char));

六、alloca从栈上分配内存

#include<alloca.h>
void *alloca(size_t size);
成功返回已经分配内存的指针

注意:
①alloca相当于分配在栈上,到时候会自动销毁,不能在定义的函数之外使用。
②alloca是最特殊的开辟栈空间方法,优点是当离开调用这个函数的时候,栈所分配的空间会自动释放(也就是free)。
③alloca不能在函数的参数中使用,因为函数参数位于栈帧固定位置。

//错误
func(x,alloca(size),x)

//正确
void funcA(void)
{
    void *y;
    y = alloca(size);
    funcB(x,y,z);
}
//当funcA返回的时候,y才销毁

④因为编译器会将alloca作为内联代码处理,并通过直接调整堆栈指针来实现。

七、内存泄露

做malloc类似的开辟空间的操作之后,当不使用的时候不做释放结果导致一直占据该内存单。(用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。)栈将稳步增长,直至抵达可用虚拟内存的上限,在之后分配内存的任何尝试都将以失败告终。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值