C++的内存分区模型

2023年1月28日 14:44 ry 286

c++程序从编译到运行过程中,内存一般分4个区存放数据,分别为代码区,全局区,栈区,堆区。代码区:存放一些二进制代码,主要是在编译过程中程序运行前生成的机器指令,具有共享和只读的特性,共享主要是可以实现多开的操作,共用同一套指令,只读防止篡改机器指令防止外挂的操作。全局区:生成时间和代码区一样,里面存放一些全局变量,静态变量,字符串常量和全局常量,程序结束后,由操作系统进行释放。以下用代码来测试下

#include<iostream>
#include<stdio.h>
using namespace std;

//全局变量
int a = 10;
int b = 20;
//const修饰的全局变量
const int a_ = 11;
int main()
{
    
    //静态变量
    static int e = 60;
    //常量
    cout<<(long long)&("今天感觉如何")<<endl;//字符串常量
  
    cout<<(long long)&a<<endl;
    cout<<(long long)&b<<endl;
  
    cout<<(long long)&e<<endl;
    
    cout<<(long long)&a_<<endl;
  
    return 0;
}

我们看下运行的结果所示,这里我用long来将16进制进行转换十进制,代码在vscode中运行,结果都是相隔非常近的,都在全局区中。栈区:程序运行过程中存放函数参数以及一些局部变量(包括const修饰的局部变量),栈区的数据由编译器管理和释放,

#include<iostream>
#include<stdio.h>
using namespace std;
//运行后 栈区 注意:不要返回局部变量的地址
//栈区的数据由编译器管理和释放
int aa = 1000;
 main()
{
    int bb = 200;


    cout<<(long long)&aa<<endl;
    cout<<(long long)&bb<<endl;

 
    return 0;
}

来看下全局区和栈区的地址区别,结果如下所示

安装最新的 PowerShell,了解新功能和改进!https://aka.ms/PSWindows

PS C:\Users\14499\Desktop\vsProjects>  & 'c:\Users\14499\.vscode\extensions\ms-vscode.cpptools-1.13.9-win32-x64\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-kqj31evw.cuq' '--stdout=Microsoft-MIEngine-Out-ujkpl4dh.hgx' '--stderr=Microsoft-MIEngine-Error-fikdbqot.s5v' '--pid=Microsoft-MIEngine-Pid-yt1xthzq.fkg' '--dbgExe=C:\Users\14499\Desktop\mingw64\bin\gdb.exe' '--interpreter=mi'
5103632
7601692
PS C:\Users\14499\Desktop\vsProjects>

可见地址相差很大。我们再验证下栈中的数据是否会随着函数的加载完成而释放,代码如下所示

#include<iostream>
#include<stdio.h>
using namespace std;
//运行后 栈区 注意:不要返回局部变量的地址
//栈区的数据由编译器管理和释放
int aa = 1000;
int *T()
{
   int cc = 20;
    return &cc;
}
int main()
{
    int bb = 200;


    cout<<(long long)&aa<<endl;
    cout<<(long long)&bb<<endl;
    int *p = T();
    cout<<*p<<endl;
 
    return 0;
}

T指针函数将cc局部变量的地址返回,看下函数执行完后是否可以输入cc的值,结果如下

Starting build...
C:/Users/14499/Desktop/mingw64/bin/g++.exe -fdiagnostics-color=always -g C:\Users\14499\Desktop\vsProjects\myCpp\stack.cpp -o C:\Users\14499\Desktop\vsProjects\myCpp\stack.exe
C:\Users\14499\Desktop\vsProjects\myCpp\stack.cpp: In function 'int* T()':
C:\Users\14499\Desktop\vsProjects\myCpp\stack.cpp:9:8: warning: address of local variable 'cc' returned [-Wreturn-local-addr]
    int cc = 20;
        ^~

Build finished with warning(s).
 *  Terminal will be reused by tasks, press any key to close it. 

出现了报错,由于cc在函数中为局部变量,随着函数的加载完成,cc也会被编译器自动回收,即执行到int *p = T()这里后,cc值和地址都不存在了,后面再打印就会报错了。因此,栈区要注意函数体中不要返回自身函数体中变量(局部变量)的地址。要解决这个报错可以使用堆区了,堆区:出现在在程序运行过程中,通过new,malloc等动态创建在堆区开辟内存,由程序员分配释放,如果程序员不释放,随着程序的结束,由操作系统最后回收,一般使用delete进行释放。

#include<iostream>
#include<stdio.h>
using namespace std;
//堆区->由程序员来管理分配释放内存,若程序员不释放,最后由操作系统回收
//c++中,主要由new来在堆区开辟内存
int * T()
{
    int *p = new int(100);
    return p;
}
int main()
{
    int *p = T();

   
    cout<<*p<<endl;
    //释放内存
    delete p;
  
    return 0;
}

结果如下

PS C:\Users\14499\Desktop\vsProjects>  & 'c:\Users\14499\.vscode\extensions\ms-vscode.cpptools-1.13.9-win32-x64\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-1bj5duq4.zgt' '--stdout=Microsoft-MIEngine-Out-4cwsic1z.kcz' '--stderr=Microsoft-MIEngine-Error-mxa45jow.wq4' '--pid=Microsoft-MIEngine-Pid-vv4iuybp.1q4' '--dbgExe=C:\Users\14499\Desktop\mingw64\bin\gdb.exe' '--interpreter=mi'
100
PS C:\Users\14499\Desktop\vsProjects> 

 

如果上述代码帮助您很多,可以打赏下以减少服务器的开支吗,万分感谢!

欢迎发表评论~

点击此处登录后即可评论


评论列表
暂时还没有任何评论哦...

赣ICP备2021001574号-1

赣公网安备 36092402000079号