ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:37.84KB ,
资源ID:19274869      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/19274869.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(大内高手常见内存错误Word文件下载.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

大内高手常见内存错误Word文件下载.docx

1、你会说p指向的内存被释放了。没错,p本身有变化吗?答案是p本身没有变化。它指向的内存仍然是有效的,你继续读写p指向的内存,没有人能拦得住你。释放掉的内存会被内存管理器重新分配,此时,野指针指向的内存已经被赋予新的意义。对野指针指向内存的访问,无论是有意还是无意的,都为此会付出巨大代价,因为它造成的后果,如同越界访问一样是不可预料的。释放内存后立即把对应指针置为空值,这是避免野指针常用的方法。这个方法简单有效,只是要注意,当然指针是从函数外层传入的时,在函数内把指针置为空值,对外层的指针没有影响。比如,你在析构函数里把this指针置为空值,没有任何效果,这时应该在函数外层把指针置为空值。4.访问

2、空指针。空指针在C/C+中占有特殊的地址,通常用来判断一个指针的有效性。空指针一般定义为0。现代操作系统都会保留从0开始的一块内存,至于这块内存有多大,视不同的操作系统而定。一旦程序试图访问这块内存,系统就会触发一个异常。操作系统为什么要保留一块内存,而不是仅仅保留一个字节的内存呢?原因是:一般内存管理都是按页进行管理的,无法单纯保留一个字节,至少要保留一个页面。保留一块内存也有额外的好处,可以检查诸如p=NULL; p1之类的内存错误。在一些嵌入式系统(如arm7)中,从0开始的一块内存是用来安装中断向量的,没有MMU的保护,直接访问这块内存好像不会引发异常。不过这块内存是代码段的,不是程序

3、中有效的变量地址,所以用空指针来判断指针的有效性仍然可行。在访问指针指向的内存时,在确保指针不是空指针。访问空指针指向的内存,通常会导致程度崩溃,或者不可预料的错误。5.引用未初始化的变量。未初始化变量的内容是随机的(像VC一类的编译器会把它们初始化为固定值,如0xcc),使用这些数据会造成不可预料的后果,调试这样的BUG也是非常困难的。对于态度严谨的程度员来说,防止这类BUG非常容易。在声明变量时就对它进行初始化,是一个编程的好习惯。另外也要重视编译器的警告信息,发现有引用未初始化的变量,立即修改过来。6.不清楚指针运算。对于一些新手来说,指针常常让他们犯糊涂。比如int *p = ; p+

4、1等于(size_t)p + 1吗老手自然清楚,新手可能就搞不清了。事实上, p+n等于(size_t)p + n * sizeof(*p)指针是C/C+中最有力的武器,功能非常强大,无论是变量指针还是函数指针,都应该掌握都非常熟练。只要有不确定的地方,马上写个小程序验证一下。对每一个细节都了然于胸,在编程时会省下不少时间。7.结构的成员顺序变化引发的错误。在初始化一个结构时,老手可能很少像新手那样老老实实的,一个成员一个成员的为结构初始化,而是采用快捷方式,如:Structsintl;char*p;main(intargc,argv)structss1= 4,abcdreturn0;以上这种

5、方式是非常危险的,原因在于你对结构的内存布局作了假设。如果这个结构是第三方提供的,他很可能调整结构中成员的相对位置。而这样的调整往往不会在文档中说明,你自然很少去关注。如果调整的两个成员具有相同数据类型,编译时不会有任何警告,而程序的逻辑上可能相距十万八千里了。正确的初始化方法应该是(当然,一个成员一个成员的初始化也行):= .l=4, .p=s2= l:4,p:8.结构的大小变化引发的错误。我们看看下面这个例子:basen;baseb;m;在OOP中,我们可以认为第二个结构继承了第一结构,这有什么问题吗?当然没有,这是C语言中实现继承的基本手法。现在假设第一个结构是第三方提供的,第二个结构是

6、你自己的。第三方提供的库是以DLL方式分发的,DLL最大好处在于可以独立替换。但随着软件的进化,问题可能就来了。当第三方在第一个结构中增加了一个新的成员int k;,编译好后把DLL给你,你直接给了客户了。程序加载时不会有任何问题,在运行逻辑可能完全改变!原因是两个结构的内存布局重叠了。解决这类错误的唯一办法就是全部重新相关的代码。解决这类错误的唯一办法就是重新编译全部代码。由此看来,DLL并不见得可以动态替换,如果你想了解更多相关内容,建议阅读COM本质论。9.分配/释放不配对。大家都知道malloc要和free配对使用,new要和delete/delete配对使用,重载了类new操作,应该

7、同时重载类的delete/delete操作。这些都是书上反复强调过的,除非当时晕了头,一般不会犯这样的低级错误。而有时候我们却被蒙在鼓里,两个代码看起来都是调用的free函数,实际上却调用了不同的实现。比如在Win32下,调试版与发布版,单线程与多线程是不同的运行时库,不同的运行时库使用的是不同的内存管理器。一不小心链接错了库,那你就麻烦了。程序可能动则崩溃,原因在于在一个内存管理器中分配的内存,在另外一个内存管理器中释放时出现了问题。10.返回指向临时变量的指针大家都知道,栈里面的变量都是临时的。当前函数执行完成时,相关的临时变量和参数都被清除了。不能把指向这些临时变量的指针返回给调用者,这

8、样的指针指向的数据是随机的,会给程序造成不可预料的后果。下面是个错误的例子:char* get_str(void)charstr = str;char* argv)p= get_str();printf(%sn,p);下面这个例子没有问题,大家知道为什么吗?get_str(void)str= get_str();11.试图修改常量在函数参数前加上const修饰符,只是给编译器做类型检查用的,编译器禁止修改这样的变量。但这并不是强制的,你完全可以用强制类型转换绕过去,一般也不会出什么错。而全局常量和字符串,用强制类型转换绕过去,运行时仍然会出错。原因在于它们是是放在.rodata里面的,而.ro

9、data内存页面是不能修改的。试图对它们修改,会引发内存错误。下面这个程序在运行时会出错:;*p112.误解传值与传引用在C/C+中,参数默认传递方式是传值的,即在参数入栈时被拷贝一份。在函数里修改这些参数,不会影响外面的调用者。如:#include stdio.hvoid get_str(char* p)p = malloc(sizeof();strcpy(p, );return;int main(int argc, char* argv)char* p = NULL;get_str(p);p=%pn, p);return 0;在main函数里,p的值仍然是空值。13.重名符号。无论是函数名

10、还是变量名,如果在不同的作用范围内重名,自然没有问题。但如果两个符号的作用域有交集,如全局变量和局部变量,全局变量与全局变量之间,重名的现象一定要坚决避免。gcc有一些隐式规则来决定处理同名变量的方式,编译时可能没有任何警告和错误,但结果通常并非你所期望的。下面例子编译时就没有警告:t.c#include更新时间:2007-7-9发表于 2006年07月12日07:59:00|评论(26)举报|收藏绗戠瑧鐢?Url=发表于Wed Jul 12 2006 08:44:00 GMT+0800 (China Standard Time)举报回复总结的很好啊Bennie发表于Wed Jul 12 20

11、06 09:15:#13这个规则并不仅仅是GCC的隐式规则,而是C的。32:所以,对于C的全局变量,要注意其默认为extern,而显式的使用static和extern来控制文件(编译单元)作用域。而那个赋值的地方,我以为使用配对的set_count更好。7116 589发表于Wed Jul 12 2006 10:27:谢谢,关注ingdrzhouweiming发表于Wed Jul 12 2006 12:10:#2内存越界问题,补充一下,还有变量强制类型转换有时会导致读写越界。TY677879发表于Wed Jul 12 2006 17:31:写得好! 在此借贵宝地揭露一下太极语言这呆B诈骗犯的无

12、耻嘴脸!universe(它自己鬼称太极语言)你个疯狗, 又在CSDN瞎叫唤了, 用你的几吧太极语言, 不如去网上down一个最新版的太骗语言而且一分钱也不花! 你这个呆B只是刻录了一个很低很低版本在光盘上, 打磨上一个universe字样, 就恬不知耻地拿出去卖钱, 当成自己开发的一样, 还要卖RMB 80块, 真不要脸! 如果你只卖2块钱的光盘介质费, 而且老老实实的将光盘上的字打磨成universe盗版太骗语言, 我还可以考虑买一张来让你有钱住进疯人院! 可惜你他妈的太不诚实了, 没办法, 我只有在这戳穿你了!你们还真以为太极语言这傻_B有个叫太极计算机的皮包公司? 这全是它自导自演的一

13、出闹剧, 它哪有啥狗屁公司哦, 加上它当妓女的老婆也才俩疯狗:太极语言你这傻_B还阴魂不散啊? 看看CSDN众多网友对你的评论吧! 你已触犯众怒, 你在与全体人民为敌! 告诉你, 人民群众的眼睛是雪亮的!太极语言你不仅人做不了, 连做狗都失败了! 野狗 - 疯狗 - 死狗, 就是你的路线图! 你已死到临头, 要想不被消灭, 只有两条路: 去疯人院, 还是劳改农场?absurd发表于Wed Jul 12 2006 21:21:to Bennie 和 drzhouweiming: 谢谢补充。xsxinguang发表于Thu Jul 13 2006 20:14:谢谢!写的很好flyingxu发表于F

14、ri Jul 14 2006 21:46:7:struct s s1 = .l=4, .p = struct s s2 = l:4, p:怎么编译啊?我在想是不是一定要gcc才行啊能解释下10吗?11:我在windows中也没有发现运行中出错。我觉得“abcd”是const的,但是操作系统这么智能,能在运行中知道这块内存是const,那真的蛮强大的。我没有在别的系统中试过哦,如果真能出错,那这个操作系统是比windows强的,我觉得。发表于Sun Jul 16 2006 09:05:to flyingxu: 据说第一种C99的标准,第二是gcc的扩展,在VC6上试了一下,两者都不支持,只能一个

15、一个的赋值。谢谢你的提醒。关于10:前者是数组,常量被拷贝到变量了,后者是指针,没有拷贝。关于11:谢谢你的测试,我只在linux上测试过,程序会出现Segmentation fault。发表于Mon Jul 17 2006 10:25:10和11其实牵涉到C语言中为了兼容而作的一个转换,的类型是const char5,它可以自然的转换到const char*,但是因为最早的类型是char5,为了大量的旧代码兼容,标准允许了转换为char*,但是这是一个受限转换,只有在特定环境下可以转换,而初始化一个char*就是其中一个。但是最好还是不要使用这个受限转换。发表于Mon Jul 17 2006

16、 21:58:to Bennie: 谢谢补充tjww发表于Mon Aug 14 2006 23:55:有一个隐蔽的错误是文件句柄错误,A线程打开一个文件,得到句柄AA,然后A线程关闭句柄AA,接着B线程打开一个文件,得到句柄BB,此时BB的句柄恰恰就是AA,当线程A接着错误地再次关闭句柄AA的时候,并不是无效操作,而是错误地关闭了线程B打开的句柄BB,此时如果线程C再打开句柄CC,则BB和CC实际上指向同一个句柄,OK,错误出现了,这种句柄开关的错误,更加隐蔽,但是一样可以用计数器的方式避免,计数器是个好东西呀注:以上分析依赖于系统分配句柄的方式,目前linux和win32都是从最小数字开始分配的发表于Tue Aug 15 2006 21:47:

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1