C语言 动态内存分配

前言 :我们知道内存分为 栈 堆 其实在计算机中是不存在差别的,只是程序员手动分类 方便处理

C语言内存分配:
1. 栈区(stack)
windows下,栈内存分配2M(确定的常数),超出了限制,提示stack overflow错误
自动分配,释放
2. 堆区(heap)
程序员手动分配释放,操作系统80%内存
3. 全局区或静态区
4. 字符常量区
5. 程序代码区

案例1 我们直接创建一个在栈区的40m大小数组

void main(){
    int aaasd[1024 * 1024 * 10];
}

这里写图片描述

结果:栈溢出

案例2 在堆区创建一个40m的数组

#include <stdlib.h>
void main(){
    int * a = malloc(sizeof(int)* 1024 * 1024 * 10);
    getchar();
}

malloc函数分配堆内存并返回对应指针 头文件stdlib.h
sizeof 返回对应变量所占字节数

结果:正常
这里写图片描述

案例3 多次动态分配堆内存 不释放

void main(){

    int * a = malloc(sizeof(int)* 1024 * 1024 * 10);

    //休眠程序10秒 头文件#include <Windows.h>
    Sleep(10000);

    a = malloc(sizeof(int)* 1024 * 1024 * 10);

    getchar();

}

在执行睡眠的时候我们看看程序所占内存大小40mb
这里写图片描述

睡眠结束后 程序内存变为80mb
这里写图片描述

我们申请了两次内存分别为40mb,发现再第二次申请的时候内存所占变为80 可见第一次申请的内存并没有释放

案例4 手动释放内存

void main(){

    int * a = malloc(sizeof(int)* 1024 * 1024 * 10);

    //释放 a所指向的内存
    free(a);

    //休眠程序10秒 头文件#include <Windows.h>
    Sleep(10000);

    a = malloc(sizeof(int)* 1024 * 1024 * 10);

    getchar();

}

上面的代码运行预期结果应该是:手动释放了第一次申请的40mb 内存 ,然后有申请了一次40mb 所以程序运行结束休眠后应该还是40mb

结果:和预期一致
这里写图片描述

案例5 申请内存另一个api

void main(){
    //第一个参数申请数量, 每个申请数量的大小 那么这里还是申请40mb
    int * a = calloc(1024*1024*10,sizeof(int));
    getchar();
}

案例6 DEMO

void main(){

    //第一个参数申请数量, 每个申请数量的大小 那么这里还是申请40mb
    int * a = calloc(1024*1024*10,sizeof(int));

    //内存申请成功
    if (a!=NULL)
    {

        //xXXXX之后释放内存
        free(a);

        a = NULL;


    }else{
        //内存申请失败
    }

    getchar();

}

realloc

内存重新分配,当你动态内存申请40mb的数组此时你不够用怎么办?便可以重新调用realoc来重新分配内存

void main(){

    //第一个参数申请数量, 每个申请数量的大小 那么这里还是申请40mb
    int * a = calloc(1024 * 1024 * 10, sizeof(int)* 2);

    //重新申请80mb 第一次申请的内存区域如果和新申请的区域不再同一段 那么 赋值数据到新内存段,并释放久指针内存区域
    int * b=realloc(a, 1024 * 1024 * 10 * sizeof(int)* 2);
    getchar();
}

这里写图片描述

注意新申请的内存 可能会在原来内存地址上基础上扩展/缩小,也有可能在某个新的内存地址段 申请一块 并且拷贝旧数据到新内存,同时释放旧内存
百度百科 :
realloc分配一个newsize的内存块,返回一个指向该内存块的指针。
如果newsize大小为0,那么释放mem_address指向的内存,并返回NULL。
如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回NULL。而原来的内存块保持不变。
现存的数据然后就被拷贝至新的位置,而老块则放回到堆上.重要的信息就是数据可能被移动

总结:

  1. realloc失败的时候,返回NULL
  2. realloc失败的时候,原来的内存不改变,不会释放也不会移动
  3. 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址
  4. 如果size为0,效果等同于free()。这里需要注意的是只对指针本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防内存泄露。
  5. 传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的
    6.传递给realloc的指针可以为空,等同于malloc。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值