前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++学习总结2——C++内存模型

C++学习总结2——C++内存模型

作者头像
王云峰
发布2019-12-25 16:06:56
5660
发布2019-12-25 16:06:56
举报
文章被收录于专栏:Yunfeng's Simple Blog

为了更直观的理解这部分内容,使用如下的程序实例进行说明:

代码语言:javascript
复制
#include<iostream>

using namespace std;

const double pi=3.1415926;    //常量

static int out=0;    //静态全局变量

int i=1;    //初始化了的全局变量

int j;    //未初始化的全局变量

void func1()
{
	static int count;    //静态局部变量

	count++;

	int i=count % 10;    //局部变量

	cout<<"count % 10="<<i<<endl;    //"count % 10="为字符串常量
}

void func2()
{
	int i=0;    //局部变量

	int *pi=&i;    //局部变量

	*pi=*pi+1;

	cout<<"i="<<i<<endl;    //"i="为字符串常量
}

int main()
{
	static int out=2;    //静态局部变量

	cout<<"out="<out<<endl;

	func1();

	func2();

	return 0;
}

在这个例子中我尽量表现了各种情况,虽然写得很不合理…

先给出C++内存的一个模型图:

对于一个C++程序,内存区域分六个部分:依次是rodata区,text区,data区,bss区,heap区和stack区。

其中rodata区和text区在加载时会合并到一个段中,该段称为常量区,该区域的内容只允许读,不允许修改;

data区和bss区在加载时合并到一个段中,该段被称为全局区,其中的内容,对程序来说,是可读可写的。

每个区的详细说明如下。

rodata

rodataread only data的缩写,只读区域,像上面程序中的pi和常量字符串”count % 10=”和”i=”都保存在该区域。

text

text区保存程序编译链接后生成的机器代码。当调用函数时,会将该区域的机器代码加载到栈中执行。

因为rodata区和text区在程序运行过程中都是不能修改的,所以在程序启动时,这两个区域又被放到一个叫做常量区的箱子中,并且在箱子外面贴上”不许修改”的标签,以防该区域的内容被修改。

data

data中存放已经初始化的 全局变量和被声明为static的局部变量。像上面程序中的全局语句“static int out=0;”,“int i=1;”以及main函数中的“static int out=2;”,这些语句定义的变量都已经被初始化,所以存放在data区。注意我这里给全局静态变量和局部静态变量起了相同的名字,都叫out,但在main函数里面输出的out=2,说明虽然都是在data区,但编译和链接过程中全局变量和局部变量的标识还是不同的,编译器不会因为名字相同而混淆两者。

bss

bss是block started by symbol的缩写,该区域存放未初始化的 全局变量和被声明为static的局部变量。在加载时该区域的值会被全部设置为0(对算术类型)或NULL(对指针类型)。上面程序中的全局语句“int j;”和func1中的语句“static int count;”中定义的j和count都在bss区。

为什么要区分初始化和未初始呢?是为了节省空间。实际上,在目标文件中,未初始化的全局变量和声明为static的局部变量不占有任何空间,只是保存了在运行时它们要占的空间的大小。在运行时开辟同样大小的空间,然后将其全部置为0。所以bss区也被戏称为“Better Save Space”。

因为data区和bss区中保存的都是全局变量和静态局部变量(跟全局变量性质一致),所以在程序启动时,这两个区域又被放到一个叫做全局区的箱子中,这个箱子中的内容是可读可写的。

heap

堆区用来存放程序运行过程中动态分配的内存。像new和malloc就在该区域上申请内存空间。该区域内存的管理必须由程序写作者来负责,也就是如果通过new或malloc申请了一块内存,在程序结束时必须通过delete或free来释放相应的内存。new和delete的内容我后面会仔细说明。

因为该区域可以由用户来申请,申请大小视情况而定,通常很不一致,所以很容易造成该区域内存的碎片化。

堆内存的大小很大,一般来讲,在32位系统下,可以达到4G,所以通常不会溢出。

stack

栈区保存函数的参数和函数内声明的变量,但声明为static的局部变量除外。栈具有后进先出的特点,很适合函数的一层层调用,所以函数调用时的变量都保存到该区中。上面程序中的main函数和func1,func2中的非static类型的变量在调用时都会加载到该区域。

栈的大小是很有限的,在Visual Studio中,默认的栈大小是1M,超过1M就会出现“stack overflow”的错误,可以通过修改默认设置来提高栈大小。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • rodata
  • text
  • data
  • bss
  • heap
  • stack
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档