用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.mzph.cn/news/66814.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#安装“Windows 窗体应用(.NET Framework)”

目录 背景: 第一步: 第二步: 第三步&#xff1a; 总结: 背景: 如下图所示:在Visual Studio Installer创建新项目的时候&#xff0c;想要添加windows窗体应用程序&#xff0c;发现里面并没有找到Windows窗体应用(.NET Framework)模板&#xff0c;快捷搜索也没有发现&#…

22.3D等距社交媒体菜单的悬停特效

效果 源码 <!doctype html> <html><head><meta charset="utf-8"><title>CSS Isometric Social Media Menu</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.…

Apache arrow顶级项目调试

Apache arrow顶级项目调试 arrow官方从7.x版本开始提供了一个gdb工具&#xff0c;叫做gdb_arrow.py&#xff0c;可以在仓库里面下载下来。 调试原理可以阅读之前写的文章&#xff1a; 玩转C调试之Python的GDB库增强 使用办法非常简单&#xff0c;直接&#xff1a; source /code…

Kubernetes技术--k8s核心技术集群的安全机制RBAC

1.引入 我们在访问k8s的集群的时候,需要经过一下几个步骤: -a:认证 -1).传输安全:对外是不暴露端口:8080,只能够在内部访问,对外使用的是6443端口。 -2).客户端认证的常用几种方式: -https证书 基于ca证书 -https token认证 通过token识别用户 -https <

springboot web开发登录拦截器

在SpringBoot中我们可以使用HandlerInterceptorAdapter这个适配器来实现自己的拦截器。这样就可以拦截所有的请求并做相应的处理。 应用场景 日志记录&#xff0c;可以记录请求信息的日志&#xff0c;以便进行信息监控、信息统计等。权限检查&#xff1a;如登陆检测&#xff…

SQL sever中用户管理

目录 一、用户管理常见方法 二、用户管理方法示例 2.1. 创建登录账户&#xff1a; 2.1.1 检查是否创建账户成功&#xff1a; 2.2. 创建数据库用户&#xff1a; 2.2.1检查用户是否创建成功&#xff1a; 2.3. 授予权限&#xff1a; 2.3.1授予 SELECT、INSERT 和 U…

原型模式:复制对象的技巧

欢迎来到设计模式系列的第六篇文章&#xff01;在前面的几篇文章中&#xff0c;我们已经学习了一些常见的设计模式&#xff0c;今天我们将继续探讨另一个重要的设计模式——原型模式。 原型模式简介 原型模式是一种创建型设计模式&#xff0c;它主要用于复制对象。原型模式通…

【教程】PyTorch Timer计时器

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] OpenCV的Timer计时器可以看这篇&#xff1a;Python Timer和TimerFPS计时工具类 Timer作用说明&#xff1a;统计某一段代码的运行耗时。 直接上代码&#xff0c;开箱即用。 import time import torch import os …

springboot设置日志输出级别

一、日志等级 trace&#xff1a;最低等级 debug&#xff1a;调试用&#xff0c;通常用于跟踪程序进展 info: 记录用&#xff0c;通常用于记录程序行为 warn&#xff1a;警告 error&#xff1a;错误 fatal&#xff1a;灾难性错误&#xff0c;最高等级 配置application.yml 实现…

L1-056 猜数字(Python实现) 测试点全过

前言&#xff1a; {\color{Blue}前言&#xff1a;} 前言&#xff1a; 本系列题使用的是&#xff0c;“PTA中的团体程序设计天梯赛——练习集”的题库&#xff0c;难度有L1、L2、L3三个等级&#xff0c;分别对应团体程序设计天梯赛的三个难度。更新取决于题目的难度&#xff0c;…

什么是BEM命名规范(Block-Element-Modifier Notation)?它有什么优势?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ BEM命名规范&#xff08;Block-Element-Modifier Notation&#xff09;⭐ BEM命名结构⭐ 优势⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎…

如何解决分库分表主键问题?

分析&回答 从问题角度出发&#xff1a;我们需要一个全局唯一的 id 来支持&#xff0c;排序问题等。这都是你实际生产环境中必须考虑的问题。可以先看下我们之前的文章分布式系统唯一ID如何生成&#xff1f; 雪花算法和雪花算法的变种是大家常用的 喵呜面试助手&#xff1…

春秋云镜 CVE-2018-1273

春秋云镜 CVE-2018-1273 Spring-data-commons 远程命令执行漏洞 靶标介绍 Spring Data是一个用于简化数据库访问&#xff0c;并支持云服务的开源框架&#xff0c;Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中&…

【算法】滑动窗口

滑动窗口应用场景 关键词&#xff1a; 满足xxx条件&#xff08;计算结果&#xff0c;出现次数&#xff0c;同时包含&#xff09; 最长/最短 子串/子数组/子序列 例如&#xff1a;长度最小的子数组 滑动窗使用思路&#xff08;寻找最长&#xff09; 核心&#xff1a;左右双指…

git大文件推送报错

报错信息 不多掰扯&#xff0c;直接上报错信息和截图 Delta compression using up to 8 threadsRPC failde; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large从以上的报错信息不难看出推送仓库的时候&#xff0c;请求体过大&#xff0c;为…

第五讲Java面向对象——类及类的成员

前言 前面几讲,我们讲解了java的基础知识,也写了很多代码,有没有发现,每次编写代码前都会新建一个类,并且开头是public class修饰。可能有些同学不知道什么是类,以及前面我们提到方法。那么本讲,就要开始深入了解他们。 在开始讲解,我们将先了解一下编程的思想,面向对…

八、SpringBoot集成Kafka

目录 一、添加依赖二、SpringBoot 生产者三、SpringBoot 消费者 一、添加依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><depend…

8.Redis-set

Set 常用命令saddsmemberssismemberscardspopsmovesrem集合间操作sinter 交集sinterstoresunion 并集sunionstoresdiff 差集sdiffstore 命令总结 内部编码应用场景使用 set来保存用户的“标签” set(集合)就是把一些有关联的数据放刀一起。 它与list的区别如下&#xff1a; 集合…

zookeeper 集群

zookeeper 集群 1、zookeeper 集群说明 initLimit 是Zookeeper用它来限定集群中的Zookeeper服务器连接到Leader的时限 syncLimit 限制了follower服务器与leader服务器之间请求和应答之间的时限 服务器名称与地址&#xff1a;集群信息&#xff08;服务器编号&#xff0c;服务器…

score_inverse_problems运行环境,pycharm重新安装,jax,jaxlib的GPU版本安装-230831

尝试运行https://github.com/yang-song/score_inverse_problems pycharm2019不支持python3.10&#xff0c;其实后来我用来3.8…… pycharm2022.3.3的安装&#xff0c;涉及激活&#xff08;淘宝5元&#xff09;&#xff0c;搜狗拼音输入&#xff08;shift不能切换输入法&#x…