您的位置:首页 > 编程语言 > C语言/C++

C语言 动态内存分配

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

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

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

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

案例4 手动释放内存

案例5 申请内存另一个api

案例6 DEMO

realloc

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。而原来的内存块保持不变。

现存的数据然后就被拷贝至新的位置,而老块则放回到堆上.重要的信息就是数据可能被移动

总结:

realloc失败的时候,返回NULL

realloc失败的时候,原来的内存不改变,不会释放也不会移动

假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址

如果size为0,效果等同于free()。这里需要注意的是只对指针本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防内存泄露。

传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的

6.传递给realloc的指针可以为空,等同于malloc。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: