[C/CPP笔记]内存五大分区(※※※※※)

序言:汽笛一声肠已断,从此天涯孤旅。凭割断愁丝恨缕。要似昆仑崩绝壁,又恰像台风扫寰宇。重比翼,和云翥。《贺新郎·别友》


【看山是山】

内存总共分为五大分区:堆区,栈区,全局静态区,常量文本区,程序代码区。

  1. 堆:是用户调用 malloc 时申请的内存空间。堆区是程序员主动分配和释放。

  2. 栈:临时创建的局部变量(一般的局部变量 + const修饰的局部变量),函数入口参数,函数返回值存放在栈区。栈区是运行时分配,结束就释放。

  3. 全局静态区:有.bss段、.data段组成,可读可写。(.bss段:未初始化的全局变量、初始化为0的全局变量、初始化为0的静态变量存放在.bss段。.data段:已经初始化的全局变量存放在.data段,静态变量存放在.data段,const定义的全局变量存放在.rodata段。)

  4. 常量区字符串存放在常量区,常量区的内容不可修改。(Code、RO-data、RW-data、ZI-data四个部分,分别代表:代码占用空间、只读常量占用空间、已初始化的可读可写的变量占用空间、未初始化的可读可写变量。)

  5. 程序代码区存放程序的代码,即CPU执行的机器指令,并且是只读的。


【看山不是山】
【C++】内存五大区详解_c++内存分区-CSDN博客

(1)程序运行前

在程序编译后,生成exe可执行程序(二进制文件),未执行该程序前分为两个区域:

代码区

  • 存放CPU执行的机器指令(二进制)
  • 代码区是共享的,目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
  • 代码区是只读的,为防止程序意外被修改了指令

全局区:(如int globalVal、static int staticGlobalVal、static int staticVal)

  • 存储全局变量、静态变量、常量、字符串常量、const修饰的全局变量
  • 全局区的数据在程序结束后由操作系统释放

(2)程序运行后

栈区(如局部变量int localVal...和指针变量int* ptr1...)

  • 由编译器自动分配释放,存放函数的参数值,局部变量等
  • 不要返回局部变量的地址,栈区开辟的数据空间由编译器自动释放

堆区(如 (int*)malloc(size of(int) * 4),开辟堆区空间)

  • 由程序员分配释放,若不释放,程序结束时由操作系统回收
  • 在C++中主要使用new关键字在堆区创建内存空间(C使用malloc、calloc...)

指针变量存放在栈区中,而指针所指向的对象或者内存地址则可以位于栈区、堆区或者全局/静态存储区。

我们平时在CLION/VS上写的代码都只是存储在磁盘上的,只有编译后形成的可执行二进制代码才被加载到内存中。


【看山还是山】

Q1:全局变量和局部变量的区别?

1. 作用域(Scope):

  • 全局变量:全局变量定义在函数之外,它们的作用域是整个程序,任何函数都可以访问这些变量。
  • 局部变量:局部变量定义在函数内部,它们的作用域仅限于定义它们的函数内部。一旦函数执行完毕,这些变量就不再可访问。

2. 生命周期(Lifetime):

  • 全局变量:全局变量的生命周期从程序开始执行直到程序结束。它们在程序启动时被分配内存,并在程序结束时释放。
  • 局部变量:局部变量的生命周期只在函数调用期间。当函数被调用时,局部变量被创建,当函数返回时,局部变量的生命周期结束,它们的内存被释放。

3. 存储区(Storage Area):

  • 全局变量:全局变量通常存储在静态存储区(也称为全局数据区),这意味着它们的存储是持久的。
  • 局部变量:局部变量通常存储在栈(stack)上,当函数被调用时,局部变量的内存被分配,函数返回时,内存被释放。

Q2:什么是段错误(Segment default)?什么原因会引起段错误?

段错误就是访问的内存超出了系统给这个程序的内存空间,也就是访问了不可访问的内存。这个内存要么是不存在(越界),要么是受到系统的保护(访问到了其他段)。

  1. 向NULL内存地址存放了一个值
  2. 内存越界,指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。 解决这类问题的办法有两个, 一是增大栈空间,二是改用动态分配,使用堆(heap)而不是栈(stack)。
  3. 指向链表的指针为NULL时,对指针的操作会Segment Default
  4. 递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。

Q3:我们在使用栈区和堆区的比较?

栈区向地址减小的方向增长

  • 在执行函数时,函数内部变量的存储在栈上。函数执行结束时,系统自动回收。
  • 栈区:大小大约只有2MB。分配容量有限
  • 执行效率很高:栈内存分配运算内置于处理器的指令集中。

堆区向地址增大的方向增长

  • 这个区域是在运行时使用的,由程序员分配和释放内存,程序结束时操作系统会对其进行回收,(程序员分配内存像malloc、free、new、delete)都是在这个区域进行的;
  • 产生内存碎片:频繁的new/delete会造成内存空间不连续,产生大量碎片,使程序效率降低。栈不会产生碎片,因为栈是先进后出的队列。
  • 空间大:一般来说,对于32位系统下,堆内存空间可以达到4G(2的32次方).从这个角度来看堆的空间是非常大的
  • 堆的效率很低:堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值