变量声明启示(一)
来源:互联网 发布:51单片机可调时钟程序 编辑:程序博客网 时间:2024/05/16 06:17
昨天闲来无事,在Linux下编了一个小程序,没有什么算法,但是出现了一个大问题,仔细检查,发现问题所在,然后通过测试就牵出了一个以前没有怎么注意到的东西,特此留念,警示一下自己。
首先给出一段简单的不能再简单的源代码:
编译执行后,首先会输出 a = 1234 ,然后需要输入一个字符数组,如果这里你输入的是少于3个字符包括3个(例如123或abc),那么下一句输出 a = 1234 ,但是如果你输入的是一个超过3个的字符(例如1234)的话,那么第二句输出的是 a = 1024,a的值发生了改变,但是程序根本没有涉及到对a的修改啊。
其实,原因出在了你输入的字符数组b上,对于b,程序中给它申请了4个字符的空间,当你输入4个字符(例如1234)的时候,其实你是向这个字符数组中存入了5个值,第5个值就是我们忽略的回车键,而当你输入超过4个字符的时候,就更显而易见了,就是你使得这个字符数组越界了!
为什么越界就会使毫不相干的另一个变量发生变化呢?原因出在变量的存储地址上,对于上面的程序,程序运行的时候,首先碰到一个int类型的变量a,编译器会把它先存入数据栈中,也就是放在了栈低,然后又碰到了一个char型的长度为4的字符数组,就又把它入栈,而且是放在了a的上面,这时a和b的地址就是连接起来的,试想一下,如果你的b变量写多了,那么就会超出自己的地址空间,也就到达了a的地址空间,相当于把a的值就给覆盖了一部分,就把a的值给改变了,这就是原因所在。
本在无聊的精神,我把上面的程序修改了一下,就更能体会到刚才的观点了:
其实只是把两个变量的声明顺序调换了一下,但是这样一来,就是b这个字符数组先进栈,a在它的上面存放,如果这时b越界了,那么它的“魔爪”就会向栈底的下面伸去,就像是把栈的地盘打破了,把下面的东西覆盖修改了,但是a还是完好无损的在它上面保留着。通过实践证明,对于上面这段代码,无论b输入什么,a都不会改变的,这也就应证了刚才的理论。
但是我并不是说提倡第二种这样的解决办法,因为它的a没有改变,只是针对这个程序是好的,但是b的越界终究还是引起了一些其他地方的改变,程序还是有bug的,所以最终的解决办法,当然就是对b的越界进行检测,如果越界了就取消操作,提示错误。对于C语言来说,它是不会自动检测数组越界问题的,因为如果这样消耗就太过庞大了,所以都是编程人员自己对数组进行检测的。
总结一下,说这些东西的目的其实不是让你把数组先定义,其实是为了让我们记住对于数组来说,如果不对它进行越界检测,会产生大麻烦的。对于一个程序成品来说,使用者不可能会看到你定义的数组的长度是多少的,所以为了程序的可靠性,就要对多方面进行谨慎的保护。
- 变量声明启示(一)
- 变量声明启示(二)
- ios 变量声明(一)
- Oracle使用手册(一)---声明变量
- Oracle使用手册(一)---声明变量
- 编译原理——变量声明语句(一)
- php学习笔记(一)变量的声明与使用
- C语言学习笔记(一)变量声明的规则
- PL/SQL学习笔记(一):声明变量
- 声明定义(变量声明、函数声明、类型声明)
- 神的启示(一):Knowing John
- hdu 1043带来的启示(一)
- 《你不知道的JavaScript》读书笔记(一):变量的声明和变量提升
- PHP学习之路(一)认识php数变量和变量声明
- Swift 基本数据类型,常/变量声明(一)
- (二)、变量的声明
- Python(2)变量声明、变量类型
- 变量声明
- 线程 (detach的作用)
- jquery jgrid用法
- 李开复:我要找什么样的人一起创业?
- JS中的几种提示框
- UML学习一:标准建模语言UML的内容
- 变量声明启示(一)
- WPF中webBrowser控件与js的交互
- 重新翻译SciTE的简体中文语言文件
- C++中引用传递与指针传递区别
- 昨日看见小学生上学,想起我的学生时代
- zoj1505 Solitaire - 双向广搜
- 初识Eclipse插件Mylyn
- Windows资源(四)版本信息资源
- [转]加速Linux程序编译