数组越界的一点心得

今天上午写个c++下的string split函数,遇到了一个非常有趣的现象。

 

没当程序运行结束的时候,都会提示堆栈溢出。

 

出错的部分大概是这样的:

while(ifs.good()) { ifs>>str; cout<

 

程序运行的时候一切正常,结果也正常,但是就是程序结束的时候跳出提示说堆栈溢出。

 

凭感觉,应该是某个参数在程序结束析构的时候由于越界导致无法完全析构,因此才跳出这个提示。

 

首先可疑的就是我定义的这个str字符数组。这个数组我是初始化为空的。

在循环内设置断点,用sizeof看str长度,发现始终是1,而strlen查看字符数,发现是不断变化的。自此发现问题所在。

 

在C中,char []类型变量的存储规则是每一个字符都存储在数组中的一个成员里,因此,如果你用sizeof和strlen分别查看数组的话,你会发现这两个值始终差1,原因是strlen不会计算'/0'入总数量中。这是C语言的正常运行机制。但是在我这个程序里,str始终是1,而strlen却不断变化,这就出现了这种局面:ifs流中的数据全部被存入了str的第一个成员内。从原理上来说这没有任何问题,因为只要ifs中buffer的数据量没有超过一个字节,那么就完全可以正常存入,只不过这种存入方法是非C语言正常存储过程。但是在运行过程中不会报错,因为赋值的过程没任何问题。

 

问题出在释放堆栈的时候,当函数生命周期结束,编译器释放堆栈的时候,会尝试释放str为基地址,长度为strlen+1的内存,但是str的size却是1,因此在释放的时候会报越界错误。数组具体内存情况分配如图:

 

程序结束的时候会尝试释放str,但是当释放到第三个元素的时候发现越界,因此会出现堆栈溢出错误。

 

 

至此,这个BUG的分析就结束了。

 

但是针对这种错误,网上有一种流行的解决方式,就是在c++基本运行时检查,取消rtc,改成默认。

 

RTC是什么,MSDN上有一段是这么说的:

 

检测局部变量(例如数组)的溢出和不足。/RTCs 将不检测当访问内存时由结构内的编译器填充导致的溢出。当使用 align (C++)/Zp(结构成员对齐)pack 时,或者以某种方式对结构元素进行排序以致要求编译器添加填充时,可能发生填充。

 

很明显,RTC一项重要的功能就是检查局部变量堆栈溢出,个人认为取消这个功能有点治标不治本,因此我个人不提倡这种解决方法,发现问题本质,从根本上找出错误所在才是正确的解决方法。

 

 

最后,我那个小程序的解决方法是什么?很简单,给数组定义固定长度,比如说,定义为256,溢出可能性基本就没了。

你可能感兴趣的:(数组越界的一点心得)