C++字符数组越界问题的一个案例分析

282 篇文章 33 订阅
16 篇文章 34 订阅

  我的学生yang1067155909给我来信,说的是C++第11周项目3 - CEmployee类继承自CPerson类中的一个细节:

贺老师:

  老师,m_szDepartment=new char[strlen(department)+1];为何需要+1呢?在测试里去掉+1后和这个效果一样啊,不太明白……求指教……
  学生,杨腾飞


  我回答:
   要给'\0'占个座。是用别人的地盘(越界的部分)保存了自己的信息了吧,不定哪次人家要用,运行结果就不一样了。这恰是最危险的问题。

  他继续追问:
   可是在定义字符数组时,比如a[4]时,可以输入5个字符,那么这个数组的'\0'的位置是不是也占用了别人的?

  我为这个机灵的同学的问题感到激动,读程序,切忌只是读,要会提问题。能自己提出问题,就一定能学好。老师给出解答,接着再提出新问题,自己解答,或再问老师,这就是交流。为着学生提出了好问题,作为老师,我骄傲。我的回答是:

  你提的问题不是一般的好,见我新发表的博文谈这个问题。


  下面就是我对这个问题的解答。不妨针对问题设计一个程序试一试。程序是:

#include <iostream> 
using namespace std;
int main() 
{ 
	char a[4];
	cin>>a;
	cout<<a<<endl;
	return 0; 
}
  亲爱的读者,读这篇文章时,请不要只“读”,打开你熟悉的编程环境,边读边运行。你会发现什么?

  输入abcd然后回车,输出是abcd。cout<<a是将字符数组当字符串输出的,显然abcd已经占满了自己的地盘a[0]到a[3],能够“如愿”输出,实际上已经侵占了不该占的内存a[4]单元。当然,恰好a[4]处给脸,就是'\0'。如果”烫烫烫烫烫烫“不必意外。

  再运行,输入abcde。我运行的结果是,在VC++6.0中,输出abcde,并弹出了我们熟悉的内存越界错误提示。在codeBlocks下,输出abcde,什么也没提示。
  请读者想想,这是一个多么凶险的Bug。

  下面再给出一个程序:

#include <iostream> 
using namespace std;
int main() 
{ 
	char a[4],b[4];
	cin>>a;
	cin>>b;
	cout<<a<<endl;
	cout<<b<<endl;
	return 0; 
}
  运行的任务交给读者了,观察输入3个字符、4个字符、5个字符的情形,也可以在多个平台上试试,针对结果想想为什么。用单步执行的手段跟踪一下内存中的数据存储,是个强烈建议的办法。

  下面是为a和b数组输入3个字符后(分别是abc和hij),利用单步执行看到的结果:

  

  下面是为a和b数组输入5个字符后(分别是abcef和hijkl),利用单步执行看到的结果:

  

  从中看出,VC++6.0中,先定义的a数组的地址大于后定义的数组b的地址,本来为a中输入了abcde,侵占了别人的地盘,随后为b输入hijkl,侵占的就是a的地盘,b[4]即a[0]为l,b[5]即a[1],存储的是'\0'!

  下图是在codeBlocks下,用同样的输入调试截出的结果,结果一样:

  

  接下来,再给一个程序,其实就是将输入a和b的顺序换了一下:

#include <iostream> 
using namespace std;
int main() 
{ 
	char a[4],b[4];
	cin>>b;
	cin>>a;
	cout<<a<<endl;
	cout<<b<<endl;
	return 0; 
}
  运行结果会是怎样?读者你自己说吧。不要忘了,用调试工具这个法宝解除你的疑惑。



  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迂者-贺利坚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值