当前位置: 首页 > news >正文

用Visual Studio 2022的.map文件来查看C++变量在内存中的布局情况

先看几个实例

代码1

#include <iostream>
int data_arr[32768];
int main()
{data_arr[1] += 11;std::cout<<"data_arr[1]: " << data_arr[1] << std::endl;return data_arr[1];
}

上述代码在Win10 X64,MSVC Release模式下编译,编译得到的二进制文件大小为15KB左右。

代码2

#include <iostream>
int data_arr[32768] = {0,0,0,0,0};
int main()
{data_arr[1] += 11;std::cout<<"data_arr[1]: " << data_arr[1] << std::endl;return data_arr[1];
}

上述代码在Win10 X64,MSVC Release模式下编译,编译得到的二进制文件大小为15KB左右。

代码3

#include <iostream>
int data_arr[32768] = {2};
int main()
{data_arr[1] += 11;std::cout<<"data_arr[1]: " << data_arr[1] << std::endl;return data_arr[1];
}

上述代码在Win10 X64,MSVC Release模式下编译,编译得到的二进制文件大小为143KB左右。

代码4

#include <iostream>
int data_arr[32768] = {1,2,3,4,5,6};
int main()
{data_arr[1] += 11;std::cout<<"data_arr[1]: " << data_arr[1] << std::endl;return data_arr[1];
}

上述代码在Win10 X64,MSVC Release模式下编译,编译得到的二进制文件大小为143KB左右。

情况分析

        为何前两份代码后两份代码编译之后的二进制文件大小会差异这么大?

        原因就是全局变量data_arr 定义的方式不同。前两份代码中data_arr变量定义但是没有初始化或初始化为0,此变量运行时实际会存放在bss段中,只存符号(只有占位符),没有初始化的具体的值,自然也就不需要在二进制文件中保存这些值,因此文件很小。

        而后两份代码中data_arr变量定义并初始化为具体的值,此变量运行时实际会存放到data段中,又因为初始化了具体的值,这些值需要保存在二进制程序源文件中,所以文件就变大了。

确认data_arr变量在内存中的布局

        在Visual Studio 2022中用对应的.map文件,来确认data_arr变量在内存中的具体布局情况,看看它们运行时到底存放在哪个内存段中。

        生成.map和了解.map文件内容请见: Visual Studio(2022)生成链接过程的.map映射文件以及.map映射文件的内容说明_含影的博客-CSDN博客

        前两份代码对应的的.map文件摘录如下:

Preferred load address is 0000000140000000Start         Length     Name                   Class0001:000013d0 00000091H .text$x                 CODE0002:00000ec8 00000788H .idata$6                DATA0003:00000000 00000040H .data                   DATA0003:00000040 00020088H .bss                    DATA0004:00000000 00000240H .pdata                  DATAAddress         Publics by Value              Rva+Base               Lib:Object0003:00000030       __scrt_ucrt_dll_is_in_use  0000000140005030     MSVCRT:ucrt_stubs.obj0003:00000040       ?data_arr@@3PAHA           0000000140005040     ccwindowsMain.obj

        从上面的.map文件内容,可以看到,data_arr变量,被分配到地址为0003:00000040这个内存空间中,而这个内存空间就是bss段(见于:0003:00000040 00020088H .bss)。

        后两份代码对应的的.map文件摘录如下:

 demo_ccwindowsPreferred load address is 0000000140000000Start         Length     Name                   Class0001:00000000 00001390H .text$mn                CODE0002:00000ec8 00000788H .idata$6                DATA0003:00000000 00020040H .data                   DATA0003:00020040 00000088H .bss                    DATA0004:00000000 00000240H .pdata                  DATAAddress         Publics by Value              Rva+Base               Lib:Object0002:00000c90       __NULL_IMPORT_DESCRIPTOR   0000000140003c90     msvcprt:MSVCP140.dll0003:00000000       ?data_arr@@3PAHA           0000000140005000     ccwindowsMain.obj

        从上面的.map文件内容,可以看到,data_arr变量,被分配到地址为0003:00000000这个内存空间中,而这个内存空间就是data段(见于:0003:00000000 00020040H .data)。

复杂一点的代码示例

#include <iostream>
#include <string>
int data_arr[32768] = {1, 2, 3, 4, 5, 6, 7, 8};
volatile const static int Major_version = 22;
volatile const float      Minor_Version = 17;
std::string               base_str_0      = "sssssAAAAA00000";
int                       parseSignal(int signal)
{static int  baseSignal = 1013;std::string base_str   = "sssssAAAAA11111";if (signal > 15){base_str += "sssssAAAAA22222" + base_str_0;signal *= base_str.size();}return signal * baseSignal;
}
int main(int argc, char** argv)
{data_arr[1] += 11;std::cout << "data_arr[1]: " << data_arr[1] << std::endl;return data_arr[1] + (Major_version << argc) + Minor_Version * argc + parseSignal(argc >> 1);
}

对应的.map内容节选如下:

 Preferred load address is 0000000140000000Start         Length     Name                   Class0001:00000000 00000050H .text$di                CODE0001:00000050 000021a0H .text$mn                CODE0001:000021f0 00000040H .text$mn$00             CODE0001:00002230 000000c0H .text$x                 CODE0001:000022f0 00000064H .text$yd                CODE0002:00000000 00000278H .idata$5                DATA0002:00000278 00000038H .00cfg                  DATA0002:000002b0 00000008H .CRT$XCA                DATA0002:000002b8 00000008H .CRT$XCAA               DATA0002:000002c0 00000008H .CRT$XCU                DATA0002:000002c8 00000008H .CRT$XCZ                DATA0002:000002d0 00000008H .CRT$XIA                DATA0002:000002d8 00000008H .CRT$XIAA               DATA0002:000002e0 00000008H .CRT$XIAC               DATA0002:000002e8 00000008H .CRT$XIZ                DATA0002:000002f0 00000008H .CRT$XPA                DATA0002:000002f8 00000008H .CRT$XPZ                DATA0002:00000300 00000008H .CRT$XTA                DATA0002:00000308 00000008H .CRT$XTZ                DATA0002:00000310 00000000H .gehcont$y              DATA0002:00000310 00000000H .gfids$y                DATA0002:00000310 000002f0H .rdata                  DATA0002:00000600 00000080H .rdata$CastGuardVftablesA DATA0002:00000680 00000080H .rdata$CastGuardVftablesC DATA0002:00000700 000001f4H .rdata$r                DATA0002:000008f4 000000a8H .rdata$voltmd           DATA0002:0000099c 000003c4H .rdata$zzzdbg           DATA0002:00000d60 00000008H .rtc$IAA                DATA0002:00000d68 00000008H .rtc$IZZ                DATA0002:00000d70 00000008H .rtc$TAA                DATA0002:00000d78 00000008H .rtc$TZZ                DATA0002:00000d80 00000418H .xdata                  DATA0002:00001198 000000ecH .xdata$x                DATA0002:00001284 00000000H .edata                  DATA0002:00001284 000000b4H .idata$2                DATA0002:00001338 00000018H .idata$3                DATA0002:00001350 00000278H .idata$4                DATA0002:000015c8 00000868H .idata$6                DATA0003:00000000 00020078H .data                   DATA0003:00020078 00000080H .data$r                 DATA0003:000200f8 00000028H .data$rs                DATA0003:00020120 000005f0H .bss                    DATA0004:00000000 000003b4H .pdata                  DATA0005:00000000 00000060H .rsrc$01                DATA0005:00000060 00000180H .rsrc$02                DATAAddress         Publics by Value              Rva+Base               Lib:Object0003:00000000       ?data_arr@@3PAHA           0000000140006000     ccwindowsMain.obj0002:000003a8       ?Major_version@@3HD        00000001400043a8     ccwindowsMain.obj0002:000003ac       ?Minor_Version@@3MD        00000001400043ac     ccwindowsMain.obj0003:00020020       ?baseSignal@?1??parseSignal@@YAHH@Z@4HA 0000000140026020     ccwindowsMain.obj0003:00020000       ?base_str_0@@3V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A 0000000140026000     ccwindowsMain.obj0002:000002c0       ?base_str_0$initializer$@@3P6AXXZEA 00000001400042c0     ccwindowsMain.obj0002:00000310       ??_C@_0BA@DGGOEDOG@sssssAAAAA00000@ 0000000140004310     ccwindowsMain.obj0002:000003b0       ??_C@_0BA@GADHIFOA@sssssAAAAA11111@ 00000001400043b0     ccwindowsMain.obj0002:000003c0       ??_C@_0BA@JKNNMPOK@sssssAAAAA22222@ 00000001400043c0     ccwindowsMain.obj

由以上代码可以看到, Major_version和Minor_Version放在只读数据区(.rdata),baseSignal这个局部静态变量放在.data数据段,而字符串常量放在只读数据段.rdata。

注:这里用 volatile 是为了防止编译器优化。

http://www.lryc.cn/news/147122.html

相关文章:

  • 使用代理突破浏览器IP限制
  • HuggingFace中的 Files and versions 如何优雅下载到本地?(Python requests,tqdm)
  • 三、原型模式
  • transformer实现词性标注
  • Java中异或操作和OTP算法
  • K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(下)
  • 女子垒球运动的发展·垒球1号位
  • Debian 30 周年,生日快乐!
  • 字符串匹配的Rabin–Karp算法
  • 傅里叶变换(FFT)笔记存档
  • ELK安装、部署、调试 (二) ES的安装部署
  • Android 13 - Media框架(8)- MediaExtractor
  • Flutter 混合开发调试
  • C语言每日一练------(Day3)
  • 14、监测数据采集物联网应用开发步骤(10)
  • Linux禅道上修改Apache 和 MySQL 默认端口号
  • 操作教程|通过1Panel开源Linux面板快速安装DataEase
  • 机器学习策略——优化深度学习系统
  • ES6中Proxy和Proxy实例
  • UDP协议的重要知识点
  • QT6为工程添加资源文件,并在ui界面引用
  • Python小知识 - 如何使用Python的Flask框架快速开发Web应用
  • Flutter 项目结构文件
  • 未找到System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.Guid) 方法错误
  • 人员位置管理,点亮矿山安全之路
  • node-red - 读写操作redis
  • 【图像处理】模板匹配的学习笔记
  • Ext JS之Ext Direct快速入门
  • 内网隧道技术学习
  • 【前端】CSS3新特性