下面的是一个简单的测试程序,基本包括了所有的变量类型,包括静态的,常量的,全局的,本地的,还有new出来的

#include <iostream>using namespace  std;const char* global_const_string = "hello world";
int global_int = 20;
static int global_static_int = 30;
int main()
{static int local_static_int = 100;int local_int = 200;int* pValue = new int(300);cout << global_const_string << global_int << global_static_int << local_static_int << local_int << *pValue;delete pValue;system("pause");return 0;
}

下面我们依次分析每个变量所属的存储区域:

我们直接用WinDbg以源码的方式调试我们的测试程序consoleTest.exe.
首先我们分析下consoleTest.exe模块的起始地址及内部数据节的分布情况, 通过!address命令:

*   400000   401000     1000 MEM_IMAGE   MEM_COMMIT  PAGE_READONLY                      Image "ConsoleTest.exe"
|-  401000   41d000    1c000 MEM_IMAGE   MEM_COMMIT  PAGE_EXECUTE_READ                  Image "ConsoleTest.exe"
|-  41d000   422000     5000 MEM_IMAGE   MEM_COMMIT  PAGE_READONLY                      Image "ConsoleTest.exe"
|-  422000   426000     4000 MEM_IMAGE   MEM_COMMIT  PAGE_WRITECOPY                     Image "ConsoleTest.exe"
|-  426000   427000     1000 MEM_IMAGE   MEM_COMMIT  PAGE_READONLY                      Image "ConsoleTest.exe"

可以看到consoleTest.exe模块在内存中的起始地址是0x400000, 接下来可以通过!dh 0x400000分析它内部的数据节分布, 并且最终我们可以得出如下结论:
地址 400000 - 401000 : PE文件头,属性是只读
地址 401000 - 41d000 : .text, 属性是只读可执行,表示代码节
地址 41d000 -  422000 : .rdata, 属性是只读, 表示只读数据
地址 422000 -  426000 : .data, 属性是写入时拷贝,表示可读写数据
地址 426000 - 427000 : .rsrc, 属性是只读,表示资源节

通过!address -f:stack命令我们可以看到:

0:000> !address -f:stack
BaseAddr EndAddr+1 RgnSize     Type       State                 Protect             Usage
-------------------------------------------------------------------------------------------
40000   13d000    fd000 MEM_PRIVATE MEM_RESERVE                                    Stack [8b0.1d0; ~0]
13d000   13e000     1000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE|PAGE_GUARD          Stack [8b0.1d0; ~0]
13e000   140000     2000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     Stack [8b0.1d0; ~0]

可以看到我们主线程的堆栈起始地址是: 13e000 - 140000

接下来我们首先分析所有全局变量的存储区域, 通过x consoletest!global*命令,让调试器列出所有在consoletest模块中global开头的调试符号:

0:000> x consoletest!global*
00422000 ConsoleTest!global_const_string = 0x0041d1dc "hello world"
00422004 ConsoleTest!global_int = 0n20
00422008 ConsoleTest!global_static_int = 0n30
004238a0 ConsoleTest!global_locale = 0x00000000
通过分析我们可以看到我们的3个全局变量global_const_string, global_int, global_static_int全都分布在422000 - 426000之间的.data可读写数据节中。
而global_const_string所指向的内容

0x0041d1dc "hello world"

则分布在41d000 -  422000 之间的.rdata只读数据节中,这个结论也符合我们平时关于全局变量存储区域的理解。

下面我们再尝试分析局部变量的存储区域,再main函数内部cout的地方设置断点,然后让程序运行到此, 然后输入dv /t /i /v命令查看所有局部变量, 可以看到

0:000> dv /t /i /v
prv local  0042200c int local_static_int = 0n100
prv local  0013ff70 int local_int = 0n200
prv local  0013ff74 int * pValue = 0x02248ff8

我们可以看到local_static_int也分布在422000 - 426000之间的.data可读写数据节中, 而local_int和pValue则都存储在13e000 - 140000之间的堆栈区域上。

而指针pValue所指向的地址0x02248ff8我们可以通过!address 0x02248ff8命令来分析, 结果是:

0:000> !address 0x02248ff8

Usage:                  Heap
Allocation Base:        021d0000
Base Address:           02248000
End Address:            02249000
Region Size:            00001000
Type:                   00020000    MEM_PRIVATE
State:                  00001000    MEM_COMMIT
Protect:                00000004    PAGE_READWRITE
More info:              !heap -p 0x21d1000
More info:              !heap -p -a 0x2248ff8

可以看到地址0x02248ff8是在堆(heap)上面。

通过上面的分析,我们验证了平时C++书上关于各种类型变量存储区域的假设,简单来说就是全局变量和静态变量会被编译到可执行文件的数据节(分只读和可读写)中, 非静态的局部变量则分配在堆栈(stack)上,而new(malloc)出来的内存则分配在堆(heap)上。

转自 http://www.cppblog.com/weiym/archive/2012/09/20/191429.html

转载于:https://www.cnblogs.com/Gotogoo/p/5381838.html

利用Windbg深入理解变量的存储模型相关推荐

  1. 【转】深入理解JVM—JVM内存模型

    原文链接 http://www.cnblogs.com/dingyingsi/p/3760447.html#top 深入理解JVM-JVM内存模型 我们知道,计算机CPU和内存的交互是最频繁的,内存是 ...

  2. 数学建模优化模型简单例题_数学建模之优化模型:存储模型

    点击上方「蓝字」关注我们 最近,为申报市级精品课程,我为我校"数学建模与科学计算"课程录制了讲课视频,下面是3.1节优化模型的第一个例子:存储模型.敬请大家批评指正! 优化模型是数 ...

  3. AI绘画能力的起源:通俗理解VAE、扩散模型DDPM、DETR、ViT/Swin transformer

    前言 2018年我写过一篇博客,叫:<一文读懂目标检测:R-CNN.Fast R-CNN.Faster R-CNN.YOLO.SSD>,该文相当于梳理了2019年之前CV领域的典型视觉模型 ...

  4. 借由ARM CORTEX-M芯片分析C程序加载和存储模型

    https://zhuanlan.zhihu.com/p/22048373 写文章 借由ARM CORTEX-M芯片分析C程序加载和存储模型 王小军 1 年前 阿军最近在忙着血氧手环嵌入式系统的技术预 ...

  5. 五大存储模型关系模型、键值存储、文档存储、列式存储、图形数据

    五大存储模型关系模型.键值存储.文档存储.列式存储.图形数据 时间:2014-06-12 16:15来源:知行网www.zhixing123.cn 编辑:麦田守望者 昨天跟一同事讨论Sybase是不是 ...

  6. 存储过程debug值not a variable_C语言变量的存储类别

    在程序中经常会使用到变量,在C程序中可以选择变量的不同存储形式,其存储类别分为静态存储和动态存储.可以通过存储类别修饰符来告诉编译器要处理什么样的类型变量,具体主要有自动(auto).静态(stati ...

  7. 剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作

    http://www.infoq.com/cn/articles/analysis-of-elasticsearch-cluster-part01?utm_source=infoq&utm_c ...

  8. Atlas元数据存储模型分析

    导语:Atlas 是一个可扩展的核心基础治理服务集 - 使企业能够有效地和高效地满足 Hadoop 中的合规性要求,并允许与整个企业数据生态系统的集成.该项目用于管理共享元数据.数据分级.审计.安全性 ...

  9. 【万字干货】OpenMetric与时序数据库存储模型分析

    摘要:解读OpenMetric规范和指标的模型定义基础上,结合当下主流的时序数据库核心存储及处理技术,尝试让用户(架构师.开发者或使用者)结合自身业务场景选择合适的产品,消除技术选型的困惑. 本文分享 ...

  10. 【华为云技术分享】ARMv8-A存储模型概述(1)

    上两期中我们介绍了处理器存储模型的一般概念,这一期我们将介绍ARMv8-A架构中的地址转换系统. 一.VMSAv8-64地址转换系统 虚拟内存系统架构(Virtual MemorySystem Arc ...

最新文章

  1. C3P0_and_pro.properties配置文档代码
  2. (组合)Binomial Showdown
  3. 学习笔记-小甲鱼Python3学习第十五讲:字符串:格式化
  4. mysql的编译_Mysql编译安装
  5. oracle 表空间
  6. springboot mongo查询固定字段_你真的会用索引么?[Mongo]
  7. 从内部重启python脚本
  8. pycharm新建项目怎么选择框架_必看!心血管疾病怎么选择检查项目?
  9. CSS定位和浮动(吸顶、居中)
  10. 发布Drools Workbench到Tomcat on Linux
  11. 斐讯K1、K2、K2P 刷机、刷入Breed 辅助工具
  12. Xcelsius 2008 在win10 64位系统下 基于OFFICE2010-x64 的安装
  13. 高校学生档案管理系统(Angularjs+HTML+CSS+bootstrap)
  14. 交换机和路由器有什么区别
  15. python爬虫实践——自动登录抽屉新热榜
  16. 怎样将系统防御升到服务器级别,H3C IPS入侵防御系统 Web配置手册-5PW104
  17. STM32F103C8T6详细引脚表
  18. 知识图谱——TransH模型原理
  19. C语言编程从键盘输入n值
  20. Unity设置字体颜色渐变

热门文章

  1. Vue实现左右菜单联动实现(更新)
  2. Docker零基础入门指南(一):Docker介绍
  3. 30分钟 带你浅入seajs源码
  4. 《数字图像处理》读书笔记:第1章 绪论
  5. Android Toast 总结
  6. 虚拟机在教学实验中的应用
  7. Visual Studio使用技巧---(1-10)
  8. 开源数据库系统之SQLite3.2.0、FireBird2.0 Alpha-1等
  9. 对vue.config.js中的代理服务器的理解
  10. Request header field mytoken is not allowed by Access-Control-Allow-Headers in preflight (请求头设置问题)