C++中数据内存分布探索笔记
2014-09-19 21:04
363 查看
今天实验室的小洲洲问了小编一个程序的问题,代码如下:
输出结果如下:
这里出现的问题就是,他尝试通过两个字节的short int类型的指针vp去读取只有一个字节的char类型的内存空间,这样就导致了vp将自动扩充去读取变量a的邻接内存空间,导致出来的结果并不是预想的65,从内存上可以有如此啊分析:
对于变量a中的字符‘A’,它对应的ASCII值为65,从内存二进制上来看,如下图:
而对于-13247而言,从内存二进制上来看,如下图:
从上面可以看到,65和-13247的低字节,也就是低八位是一样的,而这个地方正式变量a的内存空间。
但是,这样又引出了一个问题,-13247前面的高字节,也就是高八位是哪里来的呢?这里有两个猜想,或者是变量a的内存空间的高地址邻接内存空间,或者是变量a的内存空间的低地址邻接内存空间。为了验证究竟是哪个空间,小编进行了如下的测试:
结果如图:
在程序中,小编把myInt全部清空,然后在myInt中的中间两个字节填充了‘A’,这样一来,就相当于把short int的前后一个字节都进行了清空操作,避免了小洲洲出现的读取邻接内存空间随机数值的问题(当然,这里的邻接内存空间不一定是随机值,但至少不是我们的预期值)。我们可以发现,最后出现的值正是我们所期望的。
但是,我们仍然没有解决我们之前的问题,因为‘A’只占用一个字节,而该字节的前后邻接字节都是0,我们无从得知,vp指针最后扩充读取的是邻接的低地址字节还是高地址字节。基于这个思路,我们对程序加以改进:
结果如下:
我们发现,我们对myInt中间的两个字节中的高字节(在内存中其实是低地址字节)进行了填充之后,程序运行的结果并没有受影响,表明了,邻接低地址字节并没有参与vp指针的扩中读取,为了验证我们的想法,我们对程序进行了进一步的修改:
我们发现,最后的结果发生了变化,而这个变化和我们预期的是一样的,为了进一步验证小编想法的正确性,我们可以从内存进行分析:
从图上,我们可以发现,低字节,也就是低八位的值就是前面看到的65,也就是‘A’,而高八位(这里是高地址字节)正是小编刚才在代码中所设置的1。
通过以上的分析,这里小编还需要补充一个地方,可能细心的你会发现,在进行内存分析的时候,321的高字节到了程序代码中怎么又变成了低字节了呢?
其实,这里有个地方需要注意,在计算机内存中有两种内存分配方式,一种是高字节的数放在高地址,低字节的数放在低地址,还有一种则是相反,高字节的数放在低地址,低字节的数放在高地址,而小编在进行测试的时候碰到的则是第一种情况。
至此,小编简单完成了对内存数据空间分配的简单探索。
共勉之。
int main(int argc, char* argv[]) { void *vp; char a = 'A'; short int n = 97; vp = &a; cout << *(char *)vp << " " << *(short int *)vp << endl; vp = &n; cout << *(char *)vp << " " << *(short int *)vp << endl; return 0; }
输出结果如下:
这里出现的问题就是,他尝试通过两个字节的short int类型的指针vp去读取只有一个字节的char类型的内存空间,这样就导致了vp将自动扩充去读取变量a的邻接内存空间,导致出来的结果并不是预想的65,从内存上可以有如此啊分析:
对于变量a中的字符‘A’,它对应的ASCII值为65,从内存二进制上来看,如下图:
而对于-13247而言,从内存二进制上来看,如下图:
从上面可以看到,65和-13247的低字节,也就是低八位是一样的,而这个地方正式变量a的内存空间。
但是,这样又引出了一个问题,-13247前面的高字节,也就是高八位是哪里来的呢?这里有两个猜想,或者是变量a的内存空间的高地址邻接内存空间,或者是变量a的内存空间的低地址邻接内存空间。为了验证究竟是哪个空间,小编进行了如下的测试:
struct MyShortInt { char _high; char _low; }; struct MyInt { char _highest; MyShortInt _myShortInt; char _lowest; }; int main(int argc, char* argv[]) { void *vp; char a = 'A'; short int n = 97; vp = &a; MyInt myInt; memset(&myInt, 0, sizeof(MyInt)); myInt._myShortInt._low = 'A'; vp = &myInt._myShortInt._low; cout << *(char *)vp << " " << *(short int *)vp << endl; vp = &n; cout << *(char *)vp << " " << *(short int *)vp << endl; return 0; }
结果如图:
在程序中,小编把myInt全部清空,然后在myInt中的中间两个字节填充了‘A’,这样一来,就相当于把short int的前后一个字节都进行了清空操作,避免了小洲洲出现的读取邻接内存空间随机数值的问题(当然,这里的邻接内存空间不一定是随机值,但至少不是我们的预期值)。我们可以发现,最后出现的值正是我们所期望的。
但是,我们仍然没有解决我们之前的问题,因为‘A’只占用一个字节,而该字节的前后邻接字节都是0,我们无从得知,vp指针最后扩充读取的是邻接的低地址字节还是高地址字节。基于这个思路,我们对程序加以改进:
struct MyShortInt { char _high; char _low; }; struct MyInt { char _highest; MyShortInt _myShortInt; char _lowest; }; int main(int argc, char* argv[]) { void *vp; char a = 'A'; short int n = 97; vp = &a; MyInt myInt; memset(&myInt, 0, sizeof(MyInt)); myInt._myShortInt._low = 'A'; <span style="color:#ff0000;"> myInt._myShortInt._high = 1;</span> vp = &myInt._myShortInt._low; cout << *(char *)vp << " " << *(short int *)vp << endl; vp = &n; cout << *(char *)vp << " " << *(short int *)vp << endl; return 0; }
结果如下:
我们发现,我们对myInt中间的两个字节中的高字节(在内存中其实是低地址字节)进行了填充之后,程序运行的结果并没有受影响,表明了,邻接低地址字节并没有参与vp指针的扩中读取,为了验证我们的想法,我们对程序进行了进一步的修改:
struct MyShortInt { char _high; char _low; }; struct MyInt { char _highest; MyShortInt _myShortInt; char _lowest; }; int main(int argc, char* argv[]) { void *vp; char a = 'A'; short int n = 97; vp = &a; MyInt myInt; memset(&myInt, 0, sizeof(MyInt)); myInt._myShortInt._low = 'A'; <span style="color:#ff0000;">myInt._lowest = 1;</span> vp = &myInt._myShortInt._low; cout << *(char *)vp << " " << *(short int *)vp << endl; vp = &n; cout << *(char *)vp << " " << *(short int *)vp << endl; return 0; }运行结果如下:
我们发现,最后的结果发生了变化,而这个变化和我们预期的是一样的,为了进一步验证小编想法的正确性,我们可以从内存进行分析:
从图上,我们可以发现,低字节,也就是低八位的值就是前面看到的65,也就是‘A’,而高八位(这里是高地址字节)正是小编刚才在代码中所设置的1。
通过以上的分析,这里小编还需要补充一个地方,可能细心的你会发现,在进行内存分析的时候,321的高字节到了程序代码中怎么又变成了低字节了呢?
其实,这里有个地方需要注意,在计算机内存中有两种内存分配方式,一种是高字节的数放在高地址,低字节的数放在低地址,还有一种则是相反,高字节的数放在低地址,低字节的数放在高地址,而小编在进行测试的时候碰到的则是第一种情况。
至此,小编简单完成了对内存数据空间分配的简单探索。
共勉之。
相关文章推荐
- c++内存分布,代码段、全局数据区、栈、堆
- C/C++学习笔记8:内存中数据对齐的问题总结
- C++虚拟继承中_对象内存的分布_虚继承会多余分配虚表v-tab的指针vptr_图1-1清楚的描述了虚继承类对象内存的分布_转载淘宝共享数据平台
- Jim's游戏外挂学习笔记4—查找怪数据数组的内存分布和地址
- 基础备忘之c++内存分布:代码段、全局数据区、栈、堆
- C++变量在内存中的分布,堆,栈,代码,附加,数据
- C++数据内存分布
- C++学习笔记2--函数重载 复杂的数据 内存对齐 指针数组 结构与指针 传值传址传引用 联合枚举类型别名
- 学习笔记(C++中基础数据类型在内存的表现形式)
- Jim's游戏外挂学习笔记4——查找怪数据数组的内存分布和地址
- 基础备忘之c++内存分布:代码段、全局数据区、栈、堆
- C++对象中数据成员的内存分布
- C++ 内存分布,编译与运行阶段探索?(暂时不确定标题)
- Jim's游戏外挂学习笔记4—查找怪数据数组的内存分布和地址
- 转: C++动态内存创建与内存管理学习笔记[3]
- C++动态内存创建与内存管理学习笔记
- C++中的内存分布
- C++对象模型笔记:对象实例内存布局的小小结
- C++对象模型笔记:对象的三种内存布局
- 【转载】查找怪数据数组的内存分布和地址(天龙八部)