C++程序内存布局

代码区

代码区通常存放的是C++源程序的函数体经过编译后产生的二进制代码。

可执行文件在被加载进内存后,就存放在代码区。代码区的数据是只读的,尝试修改代码区的数据将会导致运行时错误。一些重要的数据,为防止在运行时被非法修改,在编译后也会被存放进代码区,如使用const限定符修饰的常变量,在编译器优化代码时,就会将程序中的常变量的值放进代码区。

全局/静态变量区

全局/静态区中存放的是全局变量或静态变量,这些变量的生命周期和程序的运行期相同。全局变量或者静态变量会增加程序模块之间的耦合性,不利于降低程序的复杂度,因此在编码时要谨慎使用全局变量。

全局变量或者静态变量一定具有初始值,要么在程序中显示指定,要么是编译器默认的零值(整型变量是0,布尔变量是false,指针变量是null,字符串是空串,等)。

在使用别的变量或者函数来为全局变量赋初值时,实际上分为了两步,第一步是全局/静态变量首先被初始化为0,第二步是,利用别的变量的值或者函数返回值来为全局/静态变量赋值。

堆区

堆的具体实现方式和管理方式与操作系统有关,不同的操作系统实现的细节不同。
堆的实现和管理的一般原理是:操作系统维护一个记录空闲内存地址的链表,当系统收到程序的内存空间的申请时,会遍历该链表,寻找第一个空间大于申请空间的结点,然后将该结点从链表中删除,并将该结点分配给程序。一般在申请到的内存空间的首地址上记录此次分配的内存空间的大小,以便在内存空间使用完毕后回收该内存空间。寻找可用空间时堆结点的大小不一定等于申请的空间的大小,系统会将多余的空间自动重新放入空闲链表中。

由于对内存空间是链表维护的,所以是不连续的内存空间。堆是向高地址拓展的数据结构,链表的遍历方向也是由低地址向高地址

堆获取内存空间的优点是方便灵活,可以获得比较大的内存空间,便于构造复杂的数据结构;缺点是获取速度较慢,容易产生内存碎片。

在C语言中,动态内存的申请和释放使用的是malloc()和free()这两个函数。C++中使用的是new和delete操作。在C++中使用new和delete会自动使用构造函数和析构函数,而调用malloc和free则不会,所以在C++中提倡使用new和delete

栈区

栈是由编译器产生的代码来管理的,不需要程序员进行栈空间的分配和释放。

在Windows平台下,栈是一块从高地址向低地址方向生长的空间,栈指针寄存器esp总是指向组后一个入栈的字节。随着新元素入栈,esp的值将逐渐减小。在程序运行时,只要栈可用空间大于程序所需空间,操作系统就会为程序分配栈空间,否则程序将报错,提示栈溢出。

在默认情况下,栈的最大容量是规定好的。在windows平台下默认栈的最大容量是1M。

C++程序的函数调用是通过栈实现的。函数返回地址、参变量、非静态局部、临时变量、函数的返回值都是分配在栈上。由于栈是由编译器管理的,所以栈的的存取效率较高,但是栈容量相对较小,所以在管理某些临时量的时候需要使用堆。

常量区

常量区是用来存放字符串常量的内存区,在程序结束后由系统释放。

下面用一个示例来说明以上内容。

#include<iostream>
int a = 1;//显示初始化全局变量,全局变量a的内存空间将会被分配在全局/静态变量区
char* p;//没有显示设置初始值,编译器自动为全局变量设置初始的零值,对于指针变量零值就是nullptr

int main()
{
	int b;//非静态局部变量,空间分布在栈上,且初始值不定
	char s[] = "hello,world!";//非静态局部字符数组,数组元素分配在栈上
	char* p;//非静态局部指针变量,内存空间分配在栈上
	char* s1 = "c++ is best";//非静态局部指针变量s1内存空间在栈上,而字符串"c++ is best"存储在常量区
	static int c = 0;//局部静态变量,内存空间被分配在全局/静态变量区

	p = new char[10];//动态申请的10字节的内存空间被分配在堆上
	strcpy(p,"c++ is best";//字符串"c++ is best"存放在常量区,编译器可能会将它与s1所指向的的"c++ is best"优化成一个地方

	return 0;	
}

程序的内存布局与目标文件分段的关系

我们知道,源文件经编译产生的但还未链接的目标文件也分成程序指令段和程序数据段,代码段书程序指令段,数据段和.bss段属于程序数据段,那程序运行时的内存布局和目标文件分段之间有什么关系呢?详见我的另一篇文章目标文件详解

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值