【空间】C++内存管理

news/2024/7/20 14:04:22 标签: 内存管理, 数据结构与算法, c/c++
1、程序的大小布局
  • 正文段(Text)用于存储指令,二进制代码,程序内容
  • 数据段(Data)用于存储已初始化的全局变量
  • BSS段(BSS)用于存储未赋值的全局变量所需的空间
    DEC是总大小,HEX是16进制描述
2、程序的内存布局

在C++中,内存分成5个区,他们分别是

  • 栈区(stack):由编译器自动分配释放,其操作方式类似于数据结构的栈(后进先出-LIFO)。在函数体中定义的局部变量通常是在栈上。

  • 堆区(heap):就是那些由new/malloc/calloc/realloc分配,free释放分配的内存块。若程序员不释放的话,程序结束时由OS回收。

  • 全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。//C++中在所有函数体外定义的全局变量,加了static修饰符后的变量不管其在程序中的哪个位置,它都会被存放在全局区(静态区)

  • 常量区(.text):常量字符串就是放在这里,程序结束后由系统释放。

  • 代码区(.data):存放程序本身的二进制代码。

图解

比如:

//例char* 和char[]的区别由此可见
int var = 0;//全局初始化区
char *p1; //全局未初始化区
void main(){
    int b;  //栈
    int s[] = "abc"; //栈
    char *p3 = "123456"; //123456在常量区,p3在栈上
    char *p2; //栈
    static int c = 0; //全局(静态)初始化区
    p1 = (char)malloc(10); //分配得来得10字节的区域在堆区
    p2 = (char)malloc(20); //分配得来得20字节的区域在堆区
    strcpy(p1, "123456"); //"123456"放在常量区,编译器可能会将它与p3所向"123456"优化成一个
}
3、堆栈和内存分配

栈(Stack)

  • 主要特点?
  • 1)相比堆而言在栈上分配要快的多
  • 2)在栈上的数据可以直接访问(不是非要使用指针访问)。
  • 3)当你程序启动时决定栈的容量上限(可以用命令指定)。
  • 4)当用栈过多时可导致栈溢出(无穷次(大量的)的递归调用,或者大量的内存分配)。
    —————————
  • 何时需要?
  • 1)较小内存的变量, 如1KB,10KB,100KB级别的内存
  • 2)较短的生存时间,如函数中的局部变量
    —————————
  • 如何分配?
  • 1)函数中定义一个局部变量即可。

堆(Heap)

  • 主要特点?
  • 1)相比在栈上分配内存要慢。
  • 2)在堆上的变量必须要手动分配和释放
  • 3)如果申请的缓冲区过大的话,可能申请失败。
  • 4)大量的分配和释放可造成内存碎片,甚至造成内存泄露
    —————————
  • 何时需要?
  • 1) 当需要分配一大块内存时,如一个很大的数组,一个很大的结构体,一个很大的类的实例。 一般当需要分配的内存达到几千个字节时,推荐在堆上分配,比如构建一个包含1000个整数的数组: int *array = malloc(1000*sizeof(int));
  • 2) 当希望变量的生存时间很长时(如全局可见)
  • 3) 当希望变量能动态的改变大小时(如能动态增加大小的数组,链表或者预先不能估计大小)
    —————————
  • 如何分配?
  • 1)C语言分配(malloc):malloc只有一个参数,即需要分配的内存的字节数。malloc的返回值有两种:当分配成功时,malloc分配size大小的内存区块,返回指向这个内存块的首地址(指针)。返回的指针是void类型的,void将会被转化成希望的指针类型。当分配失败时,返回一个指向null的空指针,一般是内存区域不足时。//以及注意,malloc分配的内存是未被初始化的。
  • 2)C语言释放(free):free函数的参数是指向一个内存区块的指针,free函数没有返回值。
  • 3)C++分配:
    int p_scalar = new int(5); //allocates an integer, set to 5. (same syntax as constructors)
    int p_array = new int[5]; //allocates an array of 5 adjacent integers. (undefined values)
    new若执行成功,它会做3件事:分配内存+调用构造函数初始化内存区域+返回内存区域的地址。new若执行失败,会抛出异常(an exception of type std::bad_alloc )

  • 4)C++释放:delete p_var

  • 5)C/C++区别:对于非内部数据类型的对象而言,对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于 malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

4、参考资料

内存管理C++
C++内存管理
char和char[]的区别
Anatomy of a Program in Memory
What a C programmer should know about memory
《程序员的自我修养——链接、装载与库》
《高质量 C++/C 编程指南》
The Descent to C
Guide to Advanced Programming in C
What and where are the stack and heap?
What’s the difference between a stack and a heap?

转载于:https://www.cnblogs.com/gwj1314/p/9444661.html


http://www.niftyadmin.cn/n/1107188.html

相关文章

RV-LINK:实现时注意事项

RV-LINK:实现时注意事项 实现 RV-LINK 时的注意事项。想到一条在这里记录一条。 https://blog.csdn.net/zoomdy/article/details/100198574 zoomdy at 163 dot com 与其它仿真器共存 很多板子有板载仿真器,并提供外部JTAG接口,可以选择使…

STL中的nth_element()方法的使用

STL中的nth_element()方法的使用 通过调用nth_element(start, startn, end) 方法可以使第n大元素处于第n位置(从0开始,其位置是下标为 n的元素),并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后&…

Red Hat套件让你的EC更轻松(转)

Red Hat套件让你的EC更轻松(转)[more]硬件要求和种类:平台:Intel处理器:Pentium III-700RAM: 512MB硬盘空间:单碟9GB SCSI硬盘CD-ROM:需要Red Hat的电子商务套件包括所有必需的工具,这些工具使得公司可以快…

截获 GDB 与 OpenOCD/GDB Server 之间的数据

截获 GDB 与 OpenOCD/GDB Server 之间的数据 可以用 socat ,也可以用 GDB 的 remotelogfile 截获 GDB 与 OpenOCD 之间的数据。 https://blog.csdn.net/zoomdy/article/details/100531857 zoomdy at 163 dot com 用 socat 截获 TCP 连接的数据 在 GDB 和 OpenO…

eclipseImport

https://jingyan.baidu.com/article/4f7d5712efd23e1a20192728.html 转载于:https://www.cnblogs.com/DixinFan/p/9159036.html

澄清Java语言接口与继承的本质(转)

澄清Java语言接口与继承的本质(转)[more]  大多数人认为,接口的意义在于顶替多重继承。众所周知Java没有c那样多重继承的机制,但是却能够实作多个接口。其实这样做是很牵强的,接口和继承是完全不同的东西,接口没有能力代替多重继…

POJ 1579 Function Run Fun 记忆化递归

典型的记忆化递归问题。 这类问题的记忆主要是利用数组记忆。那么已经计算过的值就能够直接返回。不须要进一步递归了。注意:下标越界。递归顺序不能错,及时推断是否已经计算过值了,不要多递归。 或者直接使用动态规划法填好表也是能够的。 #…

VM下Ubuntu开机出现The system is running in low-graphics mode

出现问题如https://bbs.csdn.net/topics/392267111?listlz所述,第一次碰到这个问题后查了好多方法,包括更改etc/X11/xorg.conf中的分辨率之类(个人觉得还是不要随便动这个文件为好)、重新安装VMtools都不管用。费了很多力气最后发…