C++/C的内存分配

1、概述

在调试C++/C程序时,经常会遇到这样的现象,程序运行到某个函数时突然奔溃;使用New或者malloc函数分配一段内存空间时,程序运行一段时间出现奔溃现象。总之,我们经常遇到程序奔溃的问题,而这些问题有时可能也把我们自己搞得很奔溃了。但如果我们能够了解基本的堆和栈的概念,或许可以避免那些奔溃的瞬间吧。

2、内存分配

段式内存管理架构

常见系统中,都是采用段式内存管理架构。这种架构将内存空间分为:代码段(text/code)、数据段(data)和BSS段(bss)。

2.1、代码段(text segment)

2.1.1、概述

代码段主要是指存放程序执行代码的一块内存区域。这部分区域所要占用的大小在程序运行前就已经确定,并且该内存区域通常属于只读。在代码段中,也有可能包含一些只读的常量变量。

2.1.2、program

用户程序存放在代码段中,并且一般该区域的属性只具有只读属性,某些架构下,也允许代码段为可写,及允许修改程序。

2.1.3、rodata

该段一般属于常量区,用于存放常量数据。rodata全称read only data,及指只读数据。所以一般将常量数据存放到该区域,但不是所有的常量都存放在rodata段,有的数据直接放在代码段中。

  • 常量不一定都放在rodata区域,有的立即数会直接编码在指令里,存放在代码段(.text)中。
  • 对于字符串常量,编译器会自动去掉重复的字符串,保证一个字符串在一个可执行文件中只存在一份拷贝。
  • rodata是在多个进程间是共享的,这可以提高空间利用率
  • 在有的嵌入式系统中,rodata放在ROM里,运行时直接读取ROM内存,无需要加载到内存空间里

由此可见,在rodata区域的数据,可以在对各进程间共享,可以大大提高空间利用率,甚至可以不占用RAM空间。另外由于rodata是在只读的内存页面中,是受保护的,任何修改其值的操作都会被及时发现,这样可以帮助提高程序的稳定性。

2.2、BSS段(bss segment)

2.2.1、概述

bss段通常用来存放程序中未初始化初始化为0全局变量静态局部变量

2.2.1、bss(Block Started by Symbol)

bss段属于静态内存分配,空间结构类似于stack。该区域的数据不会影响最终输出文件大小。由于是未初始化的变量,编译器生成输出文件时,就不需要记录初始值,只需记录分配的首末地址即可。同样对于初始值为0的变量,由于初始值已知,所以也不需要在输出文件中记录,只要在加载时,系统统一赋值0即可。
在大多数系统中,注意不是全部,在加载程序时,会把所有的bss段的变量全部清零,无需你手动去清零。但是像我之前接触过的TI的C2000系列处理器并不会帮你做上述的操作。所以,为了保证程序的可移植性,手动把这些变量初始化为0是比较好的编码习惯。

2.3、数据段(data segment)

2.3.1、概述

数据段主要用来存储程序中的初始化的且不为0全局变量静态变量,以及提供可供系统动态分配或者用户程序申请的内存空间。

2.3.2、静态数据(static data)

静态数据段属于静态内存分配,比较占文件空间和运行时的内存空间。

2.3.3、堆(heep)

的内存申请和释放都需要程序去控制,容易产生memory leak,生长方向向上。一般在C++中使用new操作符去申请内存空间,使用delete去释放相应的内存。这块区域的内存空间的释放系统不会去管,需应用程序自己去管理。所以当我们使用new去申请内存空间时,一定要注意使用delete去释放对应的内存空间,否则容易导致内存的泄漏。

2.3.4、栈(stack)

的内存申请和释放由系统去管理,生长方向向下,及向着内存地址减小的方向增长。主要存放函数中的局部变量,以及函数调用时,其参数也会被压入发起调用的进程栈中,并且待到函数调用结束时,函数的返回值也会被存放会栈中。由于栈的先进后出的结构特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把栈看成一个寄存、交换零时数据的内存区。

2.3.4、堆(heep)和栈(stack)的区别
对比
管理方式用户管理系统管理
空间大小几乎无限制有限制
碎片产生
生长方向向上向下
分配方式动态静态和动态
分配效率

参考文献

1、bss、data和rodata区别与联系
2、数据段、代码段、堆栈段、BSS段的区别
3、C/C++内存管理详解

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

henry.zhu51

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值