oracle数组越界,为什么栈中的数组越界后经常不崩溃,还可以正常的操作呢

使用数组也是家常便饭,但是经常出现越界使用数组也能编译通过的奇怪问题,和我们书中学习的很不一样,怎么折腾也不知道为什么,郁闷了吧!哈哈哈,别慌,这里就给你答案啦。

函数中分配的数组,不是使用动态分配的那就就是自动分配的,就是在线程栈的内存空间分配的。如果使用动态分配,即使用malloc或者new等来分配的,则是在堆中分配的。堆是是一块单独的内存块,供各个进程线程来使用的。而在栈中分配的内存,会自动分配,使用完后自动释放。我们从来都是定义一个数组变量,然后用完就不管了,根本也没有管数组的释放,因为超过数组的作用范围后,自动就销毁了,释放了占用的栈内存。

这个栈是每个进程中的,进程中创建一个线程,就会为线程在进程空间中分配一块内存给线程使用,这个内存就是线程栈。我们说的栈都是指线程栈。线程栈有一定大小,用于函数调用存储参数,记录调用函数的返回地址,用于函数返回到调用函数的位置继续执行,还用于分配局部自动变量。

栈的空间就是一段内存。我们使用数组就在栈中分配,那么对数组操作,起始就是对数组对应的栈地址进行操作。下面给出数组使用的代码,在VC中编译通过。

char t[5];

t[8]=0;

这两句代码的意思是:分配一个5个字节的数组,然后对数组中的第九个元素赋值为0.

这就已经越界了。但是在VC编译时不报错。在Debug模式下,运行会报错。而在Release模式下,没有任何问题。为什么呢?

虽然数组越界了,但是Release模式依然放行,这就给程序带来隐患,这个很可能在运行过程中破坏了线程栈,导致程序崩溃。比如,t[8]的位置刚好是调用函数返回地址,地址是四个字节,但是结果其中一个字节却被清零了,这样导致返回地址破坏了。那么函数无法返回,从而程序崩溃了。

那为什么只有在Debug模式下才能检测出来而Release模式为什么不行呢?为什么编译又能通过呢?

在Debug模式下,代码中是加入了检测跟踪代码的,可以便于调试,自然这样就可以容易检查出来。因为加入了调试代码,自然生成的EXE就比较大。而Release模式则去掉了这些跟踪检测代码,自然就不会检测这些东西了。对于这些的检测,程序员要在Debug模式下通过,最后发布是才用Release模式生成EXE,不要使用Release模式调试程序哦。

而编译通过的原因,则是因为,及时数组越界,但是因为越界的范围比较小,操作的内存地址在线程栈的范围之中,不可能出现内存操作违规的情况,编译器也没办法分清楚正确与否,所以也就通过了。

但是,编译通过和运行暂时没有出现问题,不代表没有问题,越界后是有隐患的。一般情况还是很严重的。特别要防范好,以免造成巨大的损失。

这个问题在将局部变量的地址当做函数返回值,这个问题也是很难检查出来的,如果不对这个地址赋值等,一般也不会有什么问题,一旦对这个赋值,且这个地方正好被其他参数使用了,那么就会造成线程栈破坏,导致程序崩溃。而当时你很可能发现不了这个问题,却留下了隐患。

所以,如果程序崩溃出现线程栈破坏的情况,请检查数组越界、返回局部变量地址等等问题。在开发软件时一定要养成好习惯,不要犯这种错误,一般这种错误时很难定位的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值