[C++逆向] 7 变量在内存中的位置和访问方式
| 变量类型 | 作用域 | 可访问 |
|---|---|---|
| 全局变量 | 进程作用域 | 整个进程可访问 |
| 静态变量 | 文件作用域 | 当前代码文件可访问 |
| 局部变量 | 函数作用域 | 函数内可访问 |
| {}内变量 | 块作用域 | 只能在{}内访问 |
块作用域举例
全局变量和局部变量的区别
- 全局变量
- 在PE文件中,一般是.data节表
- 在程序执行之前就已经存在了(有内存地址)
- 程序退出时销毁
- 全局变量直接通过立即数寻址
- 先定义的在低地址,后定义变量在高地址(实践得知,Release版本中不是这样的)
用户在运行文件的时候,操作系统线分析这个PE中的数据,将各个节中的数据填入对应的虚拟地址中,此时全局变量已经存在了,等PE的分析和加载完成之后,才开始执行入口点的代码,因此全局变量不受作用域影响,程序的任何位置都可以被访问到。
通过变量2访问变量1 (但是该代码在Release版本中不成立 书上的bug 哈哈)

- 局部变量
- 生命周期和函数相同
- 超出作用域之后。由栈平衡操作来释放局部变量的空间
- 通过esp或者ebp寻址
- {} 块变量
- 在{}内的局部变量生命周期和函数一样,但是编译器会编译前检查语法,限制块外代码对其访问
局部静态变量
局部静态变量实际上和全局变量是一样的,都保存再执行文件的数据区,局部静态变量会预先被当作全局变量处理,初始化实际上只是赋值
和全局变量内存结构和访问原理上是一样的,相当于全局静态变量,等价u有限制外部源码文件访问的全局变量
- 编译器通过名称粉碎法使得其他作用域对局部静态变量不可见。
- 也即是在编译器及对静态变量重新命名
有意思的

以上代码执行之后结果是什么呢?

结果居然是五个0,为什么呢?我各种仔细检查代码,发现啥问题都没有。通过调试发现,第7行执行过后,j变量还是0。
最后,书上给了答案,原因是因为为了保证局部静态变量只能被初始化一次,编译器在局部静态变量内存周围做了一个标记,每次通过检查标记判断是否已经被初始化了。如果初始化了就直接跳过。
但是!!!!!!!!!
经过我实际操作发现,上面的方法是vc6的方法,在我用的vs2019中似乎使用了新的方法。。。

这样让我很头大,但是发现了线索,就是_tls_index翻译过来就是tls索引?tls似乎听过!似乎有一个特殊的节表就是tls!通过百度,知道了tls是线程局部储存的意思。而fs里面包含了很多指针,通过查询 2Ch偏移指向的正是 线程局部储存,所以,是否可以认为,新的编译器使用了线程局部储存的方式来标记静态变量呢?
通过修改代码,把代码改成下图,可以得到正确结果。


堆变量
- 通过malloc或者new申请的空间变量,就是在堆中。
- 内存中,对结构的每个节点都是使用双向链表的形式储存的
[C++逆向] 7 变量在内存中的位置和访问方式的更多相关文章
- Java变量在内存中的存储
目录 Java变量在内存中的存储 成员变量 局部变量 总结 Java变量在内存中的存储 以下探究成员变量和局部变量在内存中的存储情况. package com.my.pac04; /** * @aut ...
- vs中调试程序查看变量在内存中的内容的方法
vs中调试程序 查看变量在内存中的内容的方法 https://blog.csdn.net/guojg1988/article/details/42922149 原文链接:http://www.sows ...
- JavaScript中的变量在内存中的具体存储形式
栈内存和堆内存 JavaScript中的变量分为基本类型和引用类型 基本类型是保存在栈内存中的简单数据段,它们的值都有固定的大小,保存在栈空间,通过按值访问 引用类型是保存在堆内存中的对象,值大小不固 ...
- string字符串常量池在内存中的位置
这里仅仅是举个简单的样例说明字符串常量池在内存中的位置. 闲言少叙,直接上代码. <span style="font-size: large;">import java ...
- JavaScript 变量类型 保存内存中的位置 和 引用
1. JavaScript变量 基本类型值在内存中占据固定大小的空间 因此被保存在栈内存中. 从一个变量向另一个变量复制基本来下的值 会创建这个值得一个副本. 引用类型的值是对象 保存在堆内存中. 包 ...
- 详解Python变量在内存中的存储
这篇文章主要是对python中的数据进行认识,对于很多初学者来讲,其实数据的认识是最重要的,也是最容易出错的.本文结合数据与内存形态讲解python中的数据,内容包括: 引用与对象 可变数据类型与不可 ...
- python中变量在内存中的存储与地址关系解析、浅度/深度copy、值传递、引用传递
---恢复内容开始--- 1.变量.地址 变量的实现方式有:引用语义.值语义 python语言中变量的实现方式就是引用语义,在变量里面保存的是值(对象)的引用(值所在处内存空间的地址).采用这种方式, ...
- C++类成员在内存中的存储及对齐方式
前言:数据对齐的基本理论参见文章:http://www.cnblogs.com/MyBlog-Richard/articles/5993448.html 一.空类的大小 C++中空类的大小是1,这是因 ...
- Linux从头学03:如何告诉 CPU,代码段、数据段、栈段在内存中什么位置?
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- Objective-C 中self.与_访问方式的区别
Objective-C中属性self.a与_a访问的区别: 在OC中我们可以通过指令@property定义属性. OC对属性封装了许多方法,同时也会自动实现一些方法,相比实例变量,感觉更加面向对象些. ...
随机推荐
- 【构造,图论,建模】Loj3629「2021 集训队互测」序列
Problem Link 有一个长为 \(n\) 的未知序列,给定 \(m\) 个限制,每个限制形如给定 \(i,j,k,x\),要求 \(a_i,a_j,a_k\) 的中位数为 \(x\).构造一个 ...
- Ant Design Vue 中Drawer自定头部的样式、内容部分的样式、弹出层的样式
<a-drawer :title="myTitle" placement="right" :visible="visible" @cl ...
- 树状数组(区间修改&&区间查询)
#include<bits/stdc++.h> #define int long long using namespace std; int n,m,x,x1,y,z; int a[100 ...
- 使用Python调用Nessus 接口实现自动化扫描
@ 目录 认证 策略模板配置 创建策略模板 任务 创建任务 启动/停止任务 获取扫描结果 获取漏洞信息 获取漏洞输出信息与漏洞知识库信息 最后总结 之前在项目中需要接入nessus扫描器,研究了一下n ...
- QAnything本地知识库问答系统:基于检索增强生成式应用(RAG)两阶段检索、支持海量数据、跨语种问答
QAnything本地知识库问答系统:基于检索增强生成式应用(RAG)两阶段检索.支持海量数据.跨语种问答 QAnything (Question and Answer based on Anythi ...
- DBGRIDEH 鼠标滚动 和 点击单元格解决思路【无意间看到,主从表】
DBGRIDEH 鼠标滚动 和 点击单元格因为我是用2个DBgridEH,主表数据变化(用的是OnCellClick),明细表也变化.现在的情况时,鼠标滚动时,明细表数据不变化好像也没看到相关的事件请 ...
- 那些年我一直在用的高效开发者工具-Typora
今天跟大家介绍一款我平时一直在用的本地Markdown工具,对比了国内外几款相似工具,Typora简洁.干练.清爽.功能完备特性深深吸引了我.我平时一般用它记录一些学习文章撰写,工作会议内容记录.项目 ...
- NC17193 简单瞎搞题
题目链接 题目 题目描述 一共有 n个数,第 i 个数是 xi xi 可以取 [li , ri] 中任意的一个值. 设 \(S = \sum{{x_i}^2}\) ,求 S 种类数. 输入描述 第一行 ...
- 【Unity3D】2D动画
1 图片处理 通过 PS 软件将以下 gif 文件中的黑色背景删除,并将其中的 18 个图层分别保存为 png 格式图片. 2 游戏对象 1)游戏对象层级结构 2)Transform组件参 ...
- CSS实现渐隐渐现效果
CSS实现渐隐渐现效果 实现渐隐渐现效果是比较常见的一种交互方式,通常的做法是控制display属性值在none和其它值之间切换,虽说功能可以实现,但是效果略显生硬,所以会有这样的需求--希望元素消失 ...
