一、栈空间
【一】、栈空间的一些基本认识
栈上可以存储任意的数据类型,但是存储的数据都是auto局部变量(关于auto局部变量在下章“变量作用域及修饰符”会讲到的,请见谅哈。),随用随开,用完自动释放,栈空间的内存是系统分配 系统释放的,不需要人手动干预.
但是系统默认的栈的空间比较小一般在2M~10M左右,这些都可以通过程序员自己来设置。
【二】、栈溢出
栈的溢出:当申请的内存空间大于系统默认的栈的空间的时候,将导致程序崩溃。
原因:1.局部变量太大 ,大于栈的默认空间大小
2.递归层次太多
【三】、函数递归与栈空间的关系
递归的本质是不断的调用函数而函数执行的时候会不断的在栈上开辟空间
给个例子:
void func(int n)
{
if(n == 1)
return ;
else
func(--n);
}
int main(void)
{
func(100000); //递归层次为100000 导致栈溢出
return 0;
}
二、堆内存
【一】、堆的存储与释放
与栈不同的是,在堆上申请内存很危险,需要程序员自己手动申请释放内存。
与栈相同的,堆也可以以存储任意的数据类型。
给个堆存储int类型的例子:
int *p=(int *)malloc(sizeof(int));
*p=400;
printf(“%d\n”,*p);//400
效果p指向的内存和int a=400;效果是一样的
p指向的内存存储了400的数值
堆上申请的内存的释放:
int *p=(int *)malloc(sizeof(int));
free(p); //释放
还有一点的是:堆的申请的内存大小可以是无穷大,在实际使用中受到了电脑的内存的实际大小和内存是不是连续。
eg:
假如一台电脑有6G的内存 ,当申请8G的内存就会失败。
【二】、内存碎片
举个简单的例子来说一下吧。什么叫做内存碎片。
在0x0010 x00200 x0030 0x0040 分别申请16字节内存,
程序运行将把x0030上申请的16字节的空间释放,
出现了内存不连续了,就出现了所谓的内存碎片。
相比于栈,由于栈是自顶上向下弹出的,绝对不可能从中间弹出数据的,所以栈是不会出现内存碎片的。