馨荣家园

室主感言:可以走错路,不可不走路,也不可总踩别人脚印走路。

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  51 随笔 :: 5 文章 :: 1328 评论 :: 18 Trackbacks
<2010年2月>
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213

News

阿荣陋室更名为馨荣家园,寓指温馨和繁荣。

留言簿(195)

随笔分类

随笔档案

文章分类

文章档案

相册

友情链接

搜索

最新评论

阅读排行榜

评论排行榜

1. 原理分析
经常有些新C++程序员问:C++的类的成员个数是不是有限制,为什么我加一个变量后程序就死了?或者说:是不是成员变量的顺序很重要,为什么我两个成员变量顺序换一换程序就不行了?凡此种种之怪现象,往往都是内存访问越界所致。

何谓内存访问越界,简单的说,你向系统申请了一块内存,在使用这块内存的时候,超出了你申请的范围。例如,你明明申请的是100字节的空间,但是你由于某种原因写入了120字节,这就是内存访问越界。内存访问越界的后果是:你的写入破坏了本不属于你的空间。

下面是一个简单的例子:
int a;
char b[16]="abcd";
int c;

a = 1;
c = 2;
printf("a=%d,c=%d\n", a,c);
memset(b, 0,32); //注意这里访问越界了,你只有16字节空间,却修改了32字节
printf("a=%d,c=%d\n", a,c);

你可以看出,在memset前后,两个printf语句打印出来的值并不一样,因为memset越界后修改了a或者c的值(由于不同编译器对变量在空间中顺序的安排可能有不同策略,因此我用两个变量,希望能抓到越界信息。对于VC,debug模式下系统添加了很多填充字节,你可能需要增加越界的数量才能看到效果)


2. 为什么增加一个变量后程序就崩溃了?
增加一个变量后,内存中变量的布局也发生了变化。如果一个内存越界破坏了一个不含指针的结构,程序虽然逻辑不对,但是不至于崩溃。但是如果增加变量后,内存访问越界破坏了一个指针,则会导致程序崩溃。

例如:

int a;
char b[128];
//bool c;
char* d=new char[128];
int e;

b[136] = '\0';
b[137] = '\0';
b[138] = '\0';
b[139] = '\0';
strcpy(d, "haha");
注意, b访问越界了8个字节位置处的4个字节。如果没有c,那么越界破坏了e变量,不会导致程序崩溃。但是加上c之后,破坏的变量可能就是d了,由于指针被破坏后,一旦访问就是内存访问违例,导致程序崩溃。

这也解释了为什么交换顺序会导致程序崩溃。如果上面情况没有变量c,你交换e和d,结构也是类似的,程序也一样要崩溃。

3. 为什么有些情况越界了程序也没错?
这主要是说这个话的人对什么是“错”没有正确的认识。程序不是只有崩溃了才是错!你破坏了别的变量,那个变量总有被使用的时候,尽管那个变量不会导致诸如程序崩溃、报警之类的严重错误,但是其计算结果必然是错误的。你说“程序没错”,是因为你根本没有发现错误而已。这种情况甚至比程序直接崩溃还要恶劣,因为程序一旦崩溃你肯定会去查,可以在导致真正严重的问题之前就把问题解决了。而如果计算错误隐藏到很晚,你的损失就可能很大了。(例如,一颗卫星上天了,你才发现一台仪器由于软件故障无法测量真正的数据,那得多少损失?)

4. 如何解决内存访问越界问题?
老实说没有好的方法。遇到这种问题,首先你得找到哪里有内存访问越界,而一个比较麻烦得问题在于,出现错误得地方往往不是真正内存越界得地方。对于内存访问越界,往往需要进行仔细得代码走查、单步跟踪并观察变量以及在调试环境得帮助下对变量进行写入跟踪(如VC6就有一旦变量被修改就break得机制)。

更重要得是,程序员要养成良好的编程习惯,在修改每个数组时一定要对这个数组有多少空间有清醒的认识,否则一旦出错,找到原因是很痛苦的事情。
posted on 2009-12-30 10:58 馨荣家园 阅读(1134) 评论(16)  编辑 收藏

评论

# re: 内存访问越界 2009-12-30 17:15 玻璃小屋

过来参观快刀荣。。。。。


# re: 内存访问越界 2010-01-01 11:19 PTFE, Teflon
顶!! blog.vckbase.com

# re: 内存访问越界 2010-01-05 20:01 fastzhao
可以用Flags查出内存越界

# re: 内存访问越界 2010-01-11 21:13 teflon ptfe
受教! 
  谢谢 !

# re: 内存访问越界 2010-01-17 01:01 大虾米(dxm)的技术博客
语重心长,VC老程序员啊

# re: 内存访问越界 2010-01-19 22:16 pxd
谢谢 学习了

# re: 内存访问越界 2010-01-27 19:13 gaojl0728
内存越界还跟堆栈的增长方式有关,一般的cpu堆栈都是向下增长的,所以你第二个例子里,数组b越界破坏的不是b后面定义的变量,而是b前面的值,因此b越界8个字节后破坏的是函数的参数值或者是函数的返回地址,欢迎大家讨论,谢谢

# vsypelrq 2010-02-02 10:26 vsypelrq
 [URL=http://twtlmlpt.com]vcqdsysw[/URL]  <a href="http://pddrrxvd.com">yxvdchyl</a>  unwhrgee http://edfragsw.com gnnpfxon ojwogrla 

# aspirin 2010-02-04 11:17 aspirin
I find it rather easy to portray a businessman. Being bland, rather cruel and incompetent comes naturally to me.

# xenical 2010-02-04 11:18 xenical
Even the best of friends need time apart.

# nolvadex 2010-02-04 11:18 nolvadex
We learn something every day, and lots of times it's that what we learned the day before was wrong.

# singulair 2010-02-04 15:02 singulair
The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.

# venlafaxine 2010-02-04 15:02 venlafaxine
Shake off all the fears of servile prejudices, under which weak minds are servilely crouched. Fix reason firmly in her seat, and call on her tribunal for every fact, every opinion. Question with boldness even the existence of a God; because, if there be one, he must more approve of the homage of reason than that of blindfolded fear.

# tamiflu hdr possum 2010-02-04 18:41 tamiflu hdr possum
The only way to get rid of a temptation is to yield to it.

# wourxiag 2010-02-05 01:17 wourxiag
cshrgpua http://ffjfunox.com ldarzbrz wsabtivb

# re: 内存访问越界 2010-03-05 09:16 christian louboutin
<a href="http://www.christianlouboutinretail.com/" title="christian louboutin"><strong>christian louboutin</strong></a>

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]