zoukankan      html  css  js  c++  java
  • 每日一问11:C++程序的内存格局

    每日一问11:C++程序的内存格局

      网上对于C++程序的内存格局有两种分法,这里两种分法都学习一下。

    四分法

      四分法是更为常见的分法,其内存格局如下:

    其中,

    1. 栈区,栈又称堆栈, 内存由编译器在需要时自动分配和释放。通常用来存储局部变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。栈运算分配内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(为运行函数而分配的局部变量、函数参数、返回地址等存放在栈区)。
    2. 堆区,堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上 (堆被扩张)/释放的内存从堆中被剔除(堆被缩减)。
    3. 全局数据区,存放全局变量、静态数据和常量;(在程序编译时期分配好的,在程序的整个运行期间都存在)。
    4. 代码区,所有类成员函数和非成员函数代码存放在代码区。该区是只读的,任何尝试对该区的写操作会导致段违法出错。代码区是被多个运行该可执行文件的进程所共享的。

    五分法

      这种分法来源于《C++内存管理技术内幕》一书,将C++中的内存分为了5个区,分别是:堆,栈,自由存储区,全局/静态存储区,常量存储区。 这种分法,没有提到代码区,将全局数据区细分为全局/静态存续区和常量存续区,将堆区分为堆和自由存储区。

    1. 栈区,同上。

    2. 堆区,内存使用new进行分配,使用delete或delete[]释放。如果未能对内存进行正确的释放,会造成内存泄漏。但在程序结束时,会由操作系统自动回收。

    3. 自由存储区:使用malloc进行分配,使用free进行回收。和堆类似。

    4. 全局/静态存储区:全局变量和静态变量被分配到同一块内存中,C语言中区分初始化和未初始化的,C++中不再区分了。

    5. 常量存储区:存储常量,不允许被修改。

    更为完善的结构

    ​ 一个进程在内存中的布局:

    ​ 其中,BBS段含了程序中未初始化全局变量,在内存中bss段全部置零。

    程序样例

    //main.cpp 
    static int s = 1;				//全局静态变量 (全局/静态存储区)
    int a = 0; 						//全局初始化区(全局/静态存储区)
    char *p1; 						//全局未初始化区 (BSS)
    int main() 
    { 
    	int b; 						//栈 
    	char s[] = "abc"; 			//栈 
    	char *p2; 					//栈 
    	char *p3 = "123456"; 		//123456在常量区,p3在栈上。 
    	static int c =0;			//局部静态变量  (全局/静态存储区)
    	p1 = (char *)malloc(10); 	//分配得来得10和20字节的区域就在堆区。
    	p2 = (char *)malloc(20); 
    	strcpy(p1, "123456"); 		//123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
       	return 0;
    }  
    

    一些问题

      自由存储区和堆的区别:从技术上来说,堆(heap)是C语言和操作系统的术语,堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能,使用malloc()、free()来申请/释放内存。而自由存储是C++中通过new和delete动态分配和释放对象的抽象概念。基本上,所有的C++编译器默认使用堆来实现自由存储。也就是说,默认的全局运算符new和delete也许会使用malloc和free的方式申请和释放存储空间,也就是说自由存储区就位于堆上。但程序员也可以通过重载操作符,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区就不位于堆上了。因此,可以这样理解,堆是操作系统维护的一块内存,是一个物理概念,而自由存储是C++中通过new与delete动态分配和释放的对象的存储区,是一个逻辑概念。堆与自由存储区并不等价。

    参考博客:

    1.C++内存管理学习堆和栈 - 云+社区 - 腾讯云 (tencent.com)

    2.C/C++程序内存的各种变量存储区域和各个区域详解_jirryzhang的博客-CSDN博客_c++内存区域

    3.什么是代码区、常量区、静态区(全局区)、堆区、栈区?_夜风的博客-CSDN博客

  • 相关阅读:
    CentOS 用命令访问网页
    ngalian(一)2:安装npm环境
    数仓建设原则探讨
    C#中获取系统时间 LZU
    判断是否是数字类 LZU
    Extjs中ComboBoxTree的实现 LZU
    SQL之学生选课数据库 LZU
    如何看书 LZU
    面向对象思想 LZU
    C#控件命名规范 LZU
  • 原文地址:https://www.cnblogs.com/honernan/p/14115189.html
Copyright © 2011-2022 走看看