C++的内存管理

在C++中,虚拟内存分为代码段、数据段、BSS段、堆区、文件映射区以及栈区六部分。其中,代码段、数据段、BSS段为静态存储区,堆区、映射区、栈区为动态存储区。

代码段:包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。

数据段:存储程序中已初始化的全局变量和静态变量。

BSS段:存储未初始化的全局变量和静态变量,以及所有被初始化为0的全局变量和静态变量。对于未初始化的全局变量和静态变量,程序运行main函数之前会统一清0,即未初始化的全局变量编译器会初始化为0。

堆区:调用new/malloc函数时在堆区动态分配内存,同时需要调用delete/free来手动释放申请的内存。当进程未调用malloc时是没有堆段区间的,只有调用malloc时才分配一个堆,并且在程序运行过程中可以动态增加堆的大小。地址增长方式为从低地址向高地址增加。分配小内存时,即小于128k时使用break指针来平移。当分配内存大于128k时,使用的是mmap(),在映射区分配。

映射区:存储动态链接库以及调用mmap函数时进行的文件映射。

栈区:使用栈空间存储函数的返回地址、参数、局部变量、返回值。地址增长方式为从高地址向低地址增长,在创建进程时会有一个最大栈大小,此最大栈大小与编译器有关,VS下为1M。但此大小可以在Linux下通过ulimit命令指定。

32位CPU可寻址4G线性空间,每个进程都有各自独立的4G逻辑地址,其中0~3G是用户态空间,3~4G是内核空间,不同进程相同的逻辑地址会映射到不同的物理地址中。

 可借助以下代码来理解内存分区的概念:

#include <stdio.h>
#include <stdlib.h>
int k = 1;
int main()
{
       int  i = 1;
       char *j;
       static int m = 1;
       char *n = "hello";
       /*变量n位于栈上,其内容为一地址,指向位于文字常量区的"hello",此时"hello"在内存中只有一份拷贝;
       而语句char a[] = "hello",则不同。此时,a是一个位于栈上的有6个元素的数组,
       并将"hello"拷贝到它所占的内存中,此时"hello"有两份拷贝。*/
       printf("栈区地址为:0x%x\n", &i);
       j = (char*)malloc(2);
       free(j);
       printf("堆区地址为:0x%x\n", j);
       printf("全局变量地址为:0x%x\n", &k);
       printf("静态变量地址为:0x%x\n", &m);
       printf("文字常量区地址为:0x%x\n", n);
       printf("程序代码区地址为:0x%x\n", &main);
       return 0;
}

const char* arr = "123";
//字符串123保存在常量区,const本来是修饰arr指向的值不能通过arr去修改,但是字符串123在常量区,本来就不能改变,所以加不加const效果都一样。

char* brr = "123";
//字符串123保存在常量区,这个与arr指针指向的是同一个位置,同样也不能通过brr去修改123的值

const char crr[] = "123";
//此时的123本来是在栈上的,但是编译器可能会做某些优化,将其放到常量区

char drr[] = "123";
//字符串123保存在栈区,可以通过drr去修改

C++里是怎么定义常量的?常量存放在内存的哪个位置?

常量在C++里定义就是一个top-level const加上对象类型,定义时必须初始化。对于局部对象,常量存放在栈区,对于全局对象,常量存放在全局/静态存储区。对于字符值常量,存放在常量存储区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值