ACG狂人

其实我更爱姐汁...

备忘随笔系列2:内存错误

接上文《备忘随笔系列1:MFC与OGRE联姻注意事项》之后,再记录一下内存错误,经过无数次莫名其妙的内存问题之后,发现一些找不着北的内存Crash问题出现的原因都很荒谬,所以本篇主要例举一下近期出现的一些怪异内存问题和让人啼笑皆非的原因所在。

问题1:编译器在编译那些访问成员变量的代码时算错了相对于this指针的偏移字节数;赋值给下面一个变量时,却修改了上面一个变量的值。
原因:与我共事的某位大仙由于酷爱使用结构体传递网络包,所以在某头文件里用#pragma pack(1)包括住了整个头文件,一不小心把#include "其他头文件"那些行也给包括了进去,其中不乏Windows.h  stl云云......
解决办法:当然那个啥......把#pragma pack(1)的位置往下去几行,还是细心点吧...浪费了整整一天调试。

问题2:从网络另一端机器发过来一个结构体,分别接收一个结构体中的多个数据成员和一次性接收整个结构体取出的数据不同。
原因:这是个很2的情形,两个相同的结构体分别在不同的头文件中,且一个有#pragma pack(1),一个没有。
解决办法:如果要用结构体传递网络包,还是共用头文件吧......

其实......很多内存问题很不好描述,我也不经常出现如上那样纠结的问题,所以下面我还是说一个最常见的内存问题(0x.....地址访问冲突)和原因吧:
“0x.....地址访问冲突”这个Crash基本上每个人都遇到,而且经常遇到,但是大部分都很容易解决。判断问题的原因可以看这几点:
原因1:如果0x....这个值很小,一般就比0大一些,而且是在访问某对象中的数据成员时出错的,那么这基本都是因为该对象指针为空,你用了空对象指针调用了代码。
原因2:如果0x...值同样很小,但是并非在访问某对象中的数据成员时出错,而是调用某函数那一行时出错的,那么这个函数十有八九是个虚函数,如果我说中的话,那原因应该如前面的原因1相同,只是这回是读取虚函数表时就崩了。
原因3:如果0x...值类似是0xcdcdcdcd和0xeeeccc或者与这相近的数,且同样是在访问数据成员或调用虚函数的时候出的问题,那么这就算是个野指针问题了,释放了就别再用啊。
原因4:内存越界,这个对程序造成的麻烦比任何麻烦都要大,但是问题并不隐蔽,记得为每个类的数据成员进行必要的初始化。
原因5:使用了memset或ZeroMemory清空一些对象或对象数组。特别是对象数组,很容易让人忽略这个问题。有些程序员会觉得某对象里都是可以这样清空的数据成员,所以便这样做了,但是往往虚函数表指针会被忽略,这个指针绝对不能一起被清空的。
总结:不要让表达索引的整形在初始化后是个未知值;不要让指针没有在初始化时被赋0值;不要不检查指针的值就拿它访问成员函数和成员数据;不要重复释放指针所指对象;不要使用释放后和未初始化的内存数据;可以的话使用智能指针;释放指针所指地址后,为指针赋0值;只有在完全是内部类型构成且没有多态的类型对象上使用memset为对象赋值。

posted on 2010-12-23 23:41 酿妹汁 阅读(1958) 评论(3)  编辑 收藏 引用 所属分类: C++备忘

评论

# re: 备忘随笔系列2:内存错误[未登录] 2010-12-25 23:26 expter

我觉得问题2就是对于数据的序列化吧,
一般情况下不用pack太节约这点内存,不然到时候调试找Bug都很难。  回复  更多评论   

# re: 备忘随笔系列2:内存错误 2010-12-25 23:28 陈梓瀚(vczh)

我艸你个姐汁……  回复  更多评论   

# re: 备忘随笔系列2:内存错误[未登录] 2010-12-26 11:21 expter

@陈梓瀚(vczh)
....你这个字。我汗。。  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理