虚拟内存

计算机组成

 
硬件:CPU,内存条,磁盘,键盘,鼠标,网卡等

软件:操作系统OS
OS目前主要由汇编及C语言编写,有大量的C语言 
通常调用OS的接口,实际就是调用C语言的接口 

后续安装/运行的软件都运行在OS上 

虚拟内存

 
一台电脑可以安装多个内存条,在OS中将这些内存条统计编码
形成一个由0,1,2,... 开始的位置编码,这就是虚拟内存
比如,4个16G的内存条,在电脑中的虚拟内存是64G 

进程的内存结构

进程使用的内存

 
一个命令或软件运行时,会启动一个进程

OS为每个进程开辟一个虚拟内存,地址都从0开始

但整个OS只有一个虚拟内存,由其他程序控制其使用的位置不冲突,比如
进程1使用了虚拟内存200-800,64G-63G,位置的地址,
进程2使用了虚拟内存1000-2000,63G-62G位置的地址... 

所以,你在电脑上运行任何一个软件,它能使用的内存范围都是0到整个电脑的内存

进程的内存结构

 
从左到右,虚拟内存地址从低到高依次是

代码区,数据区,堆,栈

代码区:数据代码,不可变,
数据区:编辑阶段初始化变量的数据,比如静态变量,全局变量等
堆:C语言中使用malloc/calloc,C++中使用new分配的空间,地址从低向高增加,

堆在低位,栈在高位 

栈:也叫堆栈,除了前面三个外,剩下所有的变量都分配在栈里,地址从高向低增加,先进后出,后进先出 

C++内存结构

C++内存结构

 
OS就是C/C++写的,因此C++的内存结构与进程的内存结构差不多 

 
#include <iostream> 
int c ;

int aa(){
    int a = 3;
}

int main(){
    int b;

    return 0;
}

 
a,b存储在栈上 
c是全局变量,存储在数据区

C++自动存储与释放

C++自动存储就是栈存储,自动释放

 
栈存储的变量数值存储在栈上,特点是定长,
虚拟地址一个格格是一个字节,Int这种4字节的,需要指针跳4个格格,
这里就是在栈上跳4个位置,从高向低位跳

从高向低的位置分配

 
#include <iostream> 

int main(){
    
    int a = 1;
    int b = 2;
    int* p1 = &a;
    int* p2 = &b;
    std::cout << "p1" << "=" << p1 << std::endl;
    std::cout << "p2" << "=" << p2 << std::endl;
    return 0;
}


$ g++ e.cpp 
$ ./a.out 
p1=0x7ffd37d7e03c
p2=0x7ffd37d7e038
 
$ ./a.out 
p1=0x7ffdf405977c
p2=0x7ffdf4059778

$ g++ e.cpp 
$ ./a.out 
p1=0x7ffde4b1276c
p2=0x7ffde4b12768

每次运行就是一个新的进程,但每次p1的地址都比p2的地址位置大,因为p1先分配 
并且8~c,从高到低是c~8,按16进制是c,b,a,9 这4个字节,
刚好四个字节一个int,然后就是下一个字节的开始地址8

 
就单个进程而言,栈这种 后进先出 的结构适合全局处理

C++动态存储new

new堆上开辟空调,返回的是地址

 
new 在堆上开辟内存空间,必须与delete配合使用

强调一下,不用new的,统一分配到栈内存上

int* a = new int;
*a = 1;  //a=0x19d8010
delete a;

C++ new与malloc区别

 
C语言中malloc可以分配单个或者一个数组的内存,realloc还可以扩容,由free释放

C++中有类的概念,malloc在为类对象分配空间时无法调用构建函数,free时无法调用析构函数 
由于诞生了new与delete

malloc是按字节分的,new人性化了一些,不用去管一个类型多少个字节,直接按数据类型分配

参考文章
    C++学习笔记(二):C++变量存储方法
    【重学C++】01| C++ 如何进行内存资源管理? 
    c++==与c内存分配释放及引用的对比(3)