c++内存空间

一个C++程序编译后占用的内存分为如下几个部分:

  • 栈:由编译器自动分配释放,存放函数的参数值,局部变量的值。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。

  • 堆:由程序员分配和释放,若程序员不释放,则程序结束时被OS回收。存放由new,malloc分配的内存,可动态扩展和收缩。

  • 全局区(静态区):全局变量和静态变量的存储是放在一起的:初始化的全局变量和初始化的静态变量在一块区域;未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

  • 文字常量区:常量字符串放在这里,程序结束后由系统释放。

  • 程序代码区:存放函数体的二进制代码。

堆和栈的主要区别

  1. 管理方式不同:栈由编译器自动管理,无需手动控制;堆由程序员控制,容易产生memory leak。
  2. 能否产生碎片:对于堆来说,频繁地new/delete势必造成内存空间的不连续,从而造成大量碎片,使程序效率降低;对于栈来说,不会存在这个问题,因为栈是后进先出的队列,一一对应,不会出现某个内存块从栈中间弹出。
  3. 生长方向:对于堆来说,生长方向向上,向着内存地址增加的地方;对于栈,生长方向向下,向着内存地址减小的方向。
  4. 分配效率:栈是计算机系统提供的数据结构,操作系统在底层对栈提供支持,分配专门的寄存器存放栈的地址,压栈出栈有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++函数库提供,显然栈的效率比堆高。
//main.cpp
int a = 0;                     //全局初始化区
char *p1;                      //全局未初始化区
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"优化成一个地方。
}

new和malloc的区别

  1. new/delete 是C++关键字(操作符),需要编译器支持。malloc/free 是库函数,需要头文件支持;
  2. 使用new 操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc 则需要显式地指出所需内存的尺寸。
  3. new 操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new 是符合类型安全性的操作符。而malloc 内存分配成功则是返回void ,需要通过强制类型转换将void指针转换成需要的类型。
  4. new 内存分配失败时,会抛出bad_alloc 异常。malloc 分配内存失败时返回NULL。
  5. new 会先调用operator new 函数,申请足够的内存(通常底层使用malloc 实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete 先调用析构函数,然后调用operator delete 函数释放内存(通常底层使用free实现)。malloc/free 是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
原文地址:https://www.cnblogs.com/cydcyd/p/13909442.html