用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 是为了防止编译器优化。
相关文章:
用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模式下编译&…...

使用代理突破浏览器IP限制
一、实验目的: 主要时了解代理服务器的概念,同时如何突破浏览器IP限制 二、预备知识: 代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站,特别是它具有一个cac…...

HuggingFace中的 Files and versions 如何优雅下载到本地?(Python requests,tqdm)
前言 在使用huggingface把玩各种大模型时,如果选择从远程加载模型,这个过程可能因为网络问题而非常耗时甚至直接失败,所以把模型、分词器等相关文件下载到本地,再直接从本地加载就成了不可回避的流程。 在进入具体版本的模型后&…...

三、原型模式
一、什么是原型模式 原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效&a…...

transformer实现词性标注
1、self-attention 1.1、self-attention结构图 上图是 Self-Attention 的结构,在计算的时候需要用到矩阵 Q(查询), K(键值), V(值)。在实际中,Self-Attention 接收的是输入(单词的表示向量 x组成的矩阵 X) 或者上一个 Encoder block 的输出。而 Q, K, V…...

Java中异或操作和OTP算法
最近在研究加密算法,发现异或操作在加密算法中用途特别广,也特别好用。下面以Java语言为例,简单记录一下异或操作,以及在算法中的使用,包括常用的OTP算法。 一,异或操作特征 1, 相同出0&#…...

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(下)
温故知新 📚第三章 Kubernetes各组件部署📗安装kubectl(可直接跳转到安装kubeadm章节,直接全部安装了)📕下载kubectl安装包📕执行kubectl安装📕验证kubectl 📗安装kubead…...
女子垒球运动的发展·垒球1号位
女子垒球运动的发展 1. 女子垒球运动的起源和发展概述 女子垒球运动,诞生于19世纪末的美国,作为棒球运动的衍生品,经过百年的积淀,已在全球范围内广泛传播,形成了丰富的赛事文化。她的起源,可以追溯到19世…...

Debian 30 周年,生日快乐!
导读近日是 Debian 日,也是由伊恩-默多克(Ian Murdock)创立的 Debian GNU/Linux 通用操作系统和社区支持的 Debian 项目 30 周年纪念日。 不管你信不信,从已故的伊恩-默多克于 1993 年 8 月 16 日宣布成立 Debian 项目,…...

字符串匹配的Rabin–Karp算法
leetcode-28 实现strStr() 更熟悉的字符串匹配算法可能是KMP算法, 但在Golang中,使用的是Rabin–Karp算法 一般中文译作 拉宾-卡普算法,由迈克尔拉宾与理查德卡普于1987年提出 “ 要在一段文本中找出单个模式串的一个匹配,此算法具有线性时间的平均复杂度࿰…...

傅里叶变换(FFT)笔记存档
参考博客:https://www.luogu.com.cn/blog/command-block/fft-xue-xi-bi-ji 目录: FFT引入复数相关知识单位根及其相关性质DFT过程(难点)DFT结论(重要)IDFT结论(重要)IDFT结论证明&…...

ELK安装、部署、调试 (二) ES的安装部署
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口操作ES,也可以利用Java API。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业…...

Android 13 - Media框架(8)- MediaExtractor
上一篇我们了解了 GenericSource 需要依赖 IMediaExtractor 完成 demux 工作,这一篇我们就来学习 android media 框架中的第二个服务 media.extractor,看看 IMediaExtractor 是如何创建与工作的。 1、MediaExtractorService media.extractor 和 media.p…...

Flutter 混合开发调试
针对Flutter开发的同学来说,大部分的应用还是Native Flutter的混合开发,所以每次改完Flutter代码,运行整个项目无疑是很费时间的。所以Flutter官方也给我们提供了混合调试的方案【在混合开发模式下进行调试】,这里以Android Stud…...

C语言每日一练------(Day3)
本专栏为c语言练习专栏,适合刚刚学完c语言的初学者。本专栏每天会不定时更新,通过每天练习,进一步对c语言的重难点知识进行更深入的学习。 今天练习题的关键字: 尼科彻斯定理 等差数列 💓博主csdn个人主页:…...

14、监测数据采集物联网应用开发步骤(10)
监测数据采集物联网应用开发步骤(9.2) Modbus rtu协议开发 本章节在《监测数据采集物联网应用开发步骤(7)》基础上实现可参考《...开发步骤(7)》调试工具,本章节代码需要调用modbus_tk组件,阅读本章节前建议baidu熟悉modbus rtu协议内容 组件安装modb…...

Linux禅道上修改Apache 和 MySQL 默认端口号
1. 修改Apache默认端口号 80 cd /opt/zbox/etc/apachevim httpd.conf :wq 保存 2. 修改MySQL默认端口号 3306 cd /opt/zbox/etc/mysql vim my.cnf :wq 保存 3. 重启服务 ./zbox restart...

操作教程|通过1Panel开源Linux面板快速安装DataEase
DataEase开源数据可视化分析工具(dataease.io)的在线安装是通过在服务器命令行执行Linux命令来进行的。但是在实际的安装部署过程中,很多数据分析师或者业务人员经常会因为不熟悉Linux操作系统及命令行操作方式,在安装DataEase的过…...

机器学习策略——优化深度学习系统
正交化(Orthogonalization) 老式电视机,有很多旋钮可以用来调整图像的各种性质,对于这些旧式电视,可能有一个旋钮用来调图像垂直方向的高度,另外有一个旋钮用来调图像宽度,也许还有一个旋钮用来…...
ES6中Proxy和Proxy实例
1.Proxy Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器” 使用方法 let p new Proxy(target, handler);其中,target 为被代理对象。handler 是一个对象,其声明了代理 target 的一些操作。p 是…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...