C/C++程式的记忆体分区的认识。可划分为四大记忆体分区:堆、栈、全局/静态存储区和代码区。不同类型的变数存放的区域不同。
基本介绍
- 中文名:C/C++记忆体分区
- 外文名:C/C++ Memory Partition
堆区:
由编程人员手动申请,手动释放,若不手动释放,程式结束后由系统回收,生命周期是整个程式运行期间。使用malloc或者new进行堆的申请,堆的总大小为机器的虚拟记忆体的大小。
说明:new操作符本质上是使用了malloc进行记忆体的申请,new和malloc的区别如下:
(1)malloc是C语言中的函式,而new是C++中的操作符。
(2)malloc申请之后返回的类型是void*,而new返回的指针带有类型。
(3)malloc只负责记忆体的分配而不会调用类的构造函式,而new不仅会分配记忆体,而且会自动调用类的构造函式。
栈区:
由系统进行记忆体的管理。主要存放函式的参数以及局部变数。在函式完成执行,系统自行释放栈区记忆体,不需要用户管理。整个程式的栈区的大小可以在编译器中由用户自行设定,VS中默认的栈区大小为1M,可通过VS手动更改栈的大小。64bits的Linux默认栈大小为10MB,可通过ulimit -s临时修改。
全局/静态存储区:
全局/静态存储区内的变数在程式编译阶段已经分配好记忆体空间并初始化。这块记忆体在程式的整个运行期间都存在,它主要存放静态变数、全局变数和常量。
注意:
(1)这里不区分初始化和未初始化的数据区,是因为静态存储区内的变数若不显示初始化,则编译器会自动以默认的方式进行初始化,即静态存储区内不存在未初始化的变数。
(2)静态存储区内的常量分为常变数和字元串常量,一经初始化,不可修改。静态存储内的常变数是全局变数,与局部常变数不同,区别在于局部常变数存放于栈,实际可间接通过指针或者引用进行修改,而全局常变数存放于静态常量区则不可以间接修改。
(3)字元串常量存储在全局/静态存储区的常量区,字元串常量的名称即为它本身,属于常变数。
(4)数据区的具体划分,有利于我们对于变数类型的理解。不同类型的变数存放的区域不同。后面将以实例代码说明这四种数据区中具体对应的变数。
代码区:
存放程式体的二进制代码。比如我们写的函式,都是在代码区的。
示例代码:
int a = 0;//静态全局变数区char *p1; //编译器默认初始化为NULLvoid main(){ int b; //栈 char s[] = "abc";//栈 char *p2 = "123456";//123456在字元串常量区,p2在栈上 static int c =0; //c在静态变数区,0为文字常量,在代码区 const int d=0; //栈 static const int d;//静态常量区 p1 = (char *)malloc(10);//分配得来得10位元组在堆区。 strcpy(p1, "123456"); //123456放在字元串常量区,编译器可能会将它与p2所指向的"123456"最佳化成一个地方}
以上所有代码,编译成二进制后存放于代码区,文字常量存放于代码区,是不可定址的。
总结
在理解C/C++记忆体分区时,常会碰到如下术语:数据区,堆,栈,静态存储区,静态区,常量区,常变数区,全局区,字元串常量区,静态常量区,静态变数区,文字常量区,代码区等等,初学者被搞得云里雾里。在这里,尝试捋清楚以上分区的关係。
数据区包括:堆,栈,全局/静态存储区。
全局/静态存储区包括:常量区(静态常量区),全局区(全局变数区)和静态变数区(静态区)。
常量区包括:字元串常量区和常变数区。
代码区:存放程式编译后的二进制代码,不可定址区。
全局/静态存储区包括:常量区(静态常量区),全局区(全局变数区)和静态变数区(静态区)。
常量区包括:字元串常量区和常变数区。
代码区:存放程式编译后的二进制代码,不可定址区。
可以说,C/C++记忆体分区其实只有两个,即代码区和数据区。