C语言在内存中的分布

先认识内存中的几个区,下面的区都在内存中,意味着掉电会丢失。但是这不意味着内存条里面真的是这样,包括操作系统的分页都只是对内存的一种管理方式,或者说是虚拟的逻辑管理。

  • 栈区(stack):由编译器自动分配释放,存放函数的参数值、局部变量、返回值等。其操作方式类似于数据结构中的栈。
  • 堆区(heap):自己分配自己释放,内存分配方式类似于数据结构的链表。
  • 全局区(静态区)(static):用于全局变量和静态变量的存储。分为:已初始化读写数据段(RW data),未初始化数据段(BSS,Block Started By Symbol)。
  • 文字常量区,即只读数据段(RO data):常量字符串和使用const定义的变量所用。
  • 程序代码区(Code或Text):存放函数体的二进制代码。

堆区和栈区属于动态区域,其他的属于静态区域,为什么这么说?来看看他们生成的过程:

  • 初始化的时候:开辟未初始化数据段。
  • 编译生成二进制代码,开辟代码段。
  • 链接:开辟只读数据段和已初始化读写数据段。
  • 运行:根据代码开辟堆区和栈区。
  • 在运行时候才开辟,不运行则不会开辟,称为动态区域是不是很合理。

来看例子加深理解:

int a=0;  //全局初始化区
char *p1; //全局未初始化区
const int A = 10;  //只读区
main()
{
    Int b;栈
    char s[]=”abc”; //栈
    char *p2; //栈
    static int c = 0; //全局(静态)初始化区
    char *p3=”123456″; //123456\0在常量区,p3在栈上。
    p1 = (char*)malloc(10);
    p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。
    strcpy(p1,”123456″); //123456\0放在常量区,编译器可能会将它与p3所向”123456″优化成一个地方。
}
堆和栈的区别

堆区和栈区用的最多,堆区用malloc或new申请,用delete和free释放;栈区自动分配和释放。这是第一点区别:申请方式。还有很多其他的区别,先看看系统是怎么开辟堆和栈的吧:

  • 栈:当线程创立的时候,系统会为其开辟一个栈区,是一块连续的向低地址扩展存储区,能分配多大取决于操作系统和硬件配置还有当时的环境。但是因为需要连续,所以不会很大。所以如果太多的递归调用(需要栈记录返回值和返回位置)和内存分配(定义10亿个变量),则会导致栈溢出,所以如果不确定变量大小不要用栈。
  • 堆:操作系统有一个记录空闲地址的链表,当我们申请堆区的时候,操作系统会遍历链表,寻找第一个空间够的(当然可能现在的系统更优化,比如找一个大小更接近的),然后将该节点从链表删除,空间分给程序,多余的部分再放回链表。(会导致碎片化)所以堆区是不连续的,向高地址扩展的存储区。很大,但是要记得释放,不然会内存泄露。如果是多线程的程序,会共享堆区,但是栈区独立,所以并行存储是堆控制的。

总结起来:

  1. 申请方式
  2. 大小不同
  3. 栈适合“杀鸡”,堆适合“宰牛”。
  4. 一个会栈溢出,一个会内存泄露。
  5. 一个向低地址连续,一个向高地址不连续。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的提千万

江山父老能容我,不使人间造孽钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值