C++内存分布
CJL爱吃鱼 人气:0C++之程序的内存分布
最近在复习C++相关的知识,整理一下。
C++的存储区主要有以下几类:
栈区:就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
堆区:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉, 那么在程序结束后,操作系统会自动回收。只new不delete会造成内存泄漏。
全局/静态存储区:全局变量和静态变量(static修饰的变量)是存储在同一块内存区域的。以前C语言还区分初始化的和未初始化的全局变量,将这两类分别存储在不同的区域,现在在C++里这两者已经不做区分了。
常量存储区:就是常量字符串或者const修饰的变量,该区域的变量不允许修改。
代码区(text):存放程序代码块的地方。
这里通过一个例子来分别看一看这些不同区域的变量。
栈区
int bb = 1; // 栈区变量 stack char s[] = "abc"; // 栈地址变量 int *p2 = NULL; // 栈地址变量
将以上变量的地址分别打印
(lldb) p &bb
(int *) $0 = 0x00000003040cf224
(lldb) p &s
(char (*)[4]) $1 = 0x00000003040cf220
(lldb) p &p2
(int **) $2 = 0x00000003040cf218
(lldb)
可以看到这几个存储在栈区的变量是挨着存储,且地址依次从高到低变化。
堆区:
int *ph = new int(10); // ph在栈区,指向堆(heap)区变量 (地址增长) int *ph2 = new int(20); // 堆(heap)区变量
分别打印指针的地址和指针指向的地址的值
(lldb) p &ph
(int **) $0 = 0x00000003040cf1f0 // 指针的地址,在栈区
(lldb) p &ph2
(int **) $1 = 0x00000003040cf1e8 // 指针的地址,在栈区
(lldb) p ph
(int *) $2 = 0x0000000108e20db0 // 指针指向的地址,在堆区
(lldb) p ph2
(int *) $3 = 0x0000000108e20900 // 指针指向的地址,在堆区
从上面的例子可以看到,指针本身存储在栈区,其地址相邻且从高到低变化。
指针指向的地址在另一块区域,该区域称为堆区,该区域的地址是从低到高变化的。但是并不具有相邻的特点。
全局/静态存储区
int globleA = 0; // 全局初始化区 int *pPoint; // 全局未初始化区 默认为0,指针为NULL int main(int argc, const char * argv[]) { static int c = 0; // 全局(静态)初始化区 (和全局变量是一样的) return 0; }
打印出地址和结果:
(lldb) p &globleA
(int *) $0 = 0x00000001000080d8 // 全局/静态变量区
(lldb) p &pPoint
(int **) $1 = 0x00000001000080e0 // 全局/静态变量区
(lldb) p &c
(int *) $2 = 0x00000001000080d4 // 全局静态变量区
(lldb) p pPoint
(int *) $3 = 0x0000000000000000 // 未初始化的值为NULL
常量区
char *p3 = "123456"; // p3在栈区,但是它指向的变量在常量区(无法改变), 指针可以跨区域访问
(lldb) p p3
(char *) $3 = 0x0000000100003f43 "123456" // 常量区
(lldb) p &p3
(char **) $4 = 0x00000003040cf210 // 栈区
代码区
就是代码存放的地方。
下面用一张图片总结:
加载全部内容