数组越界 内存分配

ifndef冬瓜 2018-08-02 03:10:26

int a = 10;
int arr[2];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

C++是不检查数组越界的,所以我这么写能通过编译可能顺利运行。在声明的时候,已经为对象分配了内存,且这些都是分配在栈中的,即地址从高往低,所以a,arr[1],arr[0],我们举个例子,假如&a是0x22fef8, 那么&arr[1],&arr[0]分别是0x22fef4, 0x22fef0。
当我要为arr[2]赋值的时候,其实,C++是将arr[1]后面的四个字节的内存当做int来处理,如果这部分内存不是int型,比如是char,那么这块内存就会变成“垃圾”(大概这么称呼吧),而正好,如果这块内存是int型,那么内容就会被改变。如果把对数组的声明放在a之前,a就不会被改变:

int main()
{
int a = 10;
int arr[2];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
cout << a << " " << arr[0] << " " << arr[1] << " " << arr[2] << endl;
cout << &a << " " << &arr[0] << " " << &arr[1] << " " << &arr[2] << endl;

return 0;
}


但是当我把a声明为double时,能看到a的地址和arr[2]的地址是相同的,但是a的值还是刚开始给他定义的值,而非arr[3]的值或者“垃圾”。而改为long long的话,则会被覆盖。

我想知道一个double值在内存中是怎么存在的,或者说怎么看内存中储存的内容,以及这个现象的原因是什么?
...全文
248 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Moye-mio 2019-09-03
  • 打赏
  • 举报
回复
楼上说没意义的怕是没学过系统级编程吧(无奈
EINPROGRESS 2018-08-04
  • 打赏
  • 举报
回复
让我们再来看a为double时候,可以看到a内存是$esp + 0x10,占用8字节。arr[2]指向内存是$esp+0x20。因此写arr[2]不会影响a。因此其实越界写会不会影响其他变量,取决于内存分布。同时内存是没有类型的概念的。语言的类型转换到底层汇编是操作内存大小以及相应操作指令。
0x080486bd <+9>: sub $0x20,%esp # 分配局部变量内存
0x080486c0 <+12>: fldl 0x8048938
0x080486c6 <+18>: fstpl 0x10(%esp) # a = 10
0x080486ca <+22>: movl $0x1,0x18(%esp) # arr[0] = 1
0x080486d2 <+30>: movl $0x2,0x1c(%esp) # arr[1] = 2
0x080486da <+38>: movl $0x3,0x20(%esp) # arr[2] = 3
EINPROGRESS 2018-08-04
  • 打赏
  • 举报
回复
首先我认为楼主会去研究这些底层的实现是值得肯定的。我们先看a为整型的时候发生了什么。反汇编取初始化那段来看。可以看到编译器为a变量分配的内存是$esp + 0x1c。由于arr[2]的指向内存也是$esp + 0x1c。因此其实arr[2] 与 a是指向同段内存。
0x0804868d <+9>: sub $0x20,%esp # 为局部变量分配内存
0x08048690 <+12>: movl $0xa,0x1c(%esp) # a = 10
0x08048698 <+20>: movl $0x1,0x14(%esp) # arr[0] = 1
0x080486a0 <+28>: movl $0x2,0x18(%esp) # arr[1] = 2
0x080486a8 <+36>: movl $0x3,0x1c(%esp) # arr[2] = 3
ifndef冬瓜 2018-08-03
  • 打赏
  • 举报
回复
引用 5 楼 zhouqunhai 的回复:
没有意义这个问题

没有意义这个回复
zhouqunhai 2018-08-02
  • 打赏
  • 举报
回复
没有意义这个问题
赵4老师 2018-08-02
  • 打赏
  • 举报
回复
VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533
赵4老师 2018-08-02
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节中都有值且都是可读写的,从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
ShanTUT 2018-08-02
  • 打赏
  • 举报
回复
做这样的实验有什么意义呢,正常写代码时候,谁也不会刻意让自己的数组越界吧?
ChongQingJin28 2018-08-02
  • 打赏
  • 举报
回复
应该是依赖于编译器实现吧 C++的标准定义过数据的存储方式吗?

我觉得应该不会吧(我猜的)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧