【空间】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