关于delete this及堆破坏检测方法

关于delete this及堆破坏检测方法

ID:28525834

大小:63.76 KB

页数:4页

时间:2018-12-10

关于delete this及堆破坏检测方法_第1页
关于delete this及堆破坏检测方法_第2页
关于delete this及堆破坏检测方法_第3页
关于delete this及堆破坏检测方法_第4页
资源描述:

《关于delete this及堆破坏检测方法》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库

1、关于deletethis及堆破坏检测方法作者: Bruce  日期:2012年06月03日04:20周日0条评论151人阅读程序BUG往往因为无知和无意识悄然埋下。在网络库中,我写了这么一段关闭socket的代码:viewsourceprint?01void CTcpSocket::Destroy(BOOL bNotifyClosed)02{03    if (m_nLinkStatus!=LinkNotOpen)04    {05        m_nLinkStatus=LinkNotOpen;06 07        ::shutdown(m_h

2、Sock,SD_SEND);08        ::closesocket(m_hSock);09        if (bNotifyClosed)10            OnClose(::WSAGetLastError());  //Tag#1:通知应用层socket已关闭11        m_hSock=INVALID_SOCKET;          //Tag#2:socket句柄置为无效12    }13}因为这段代码,服务器程序没跑多久就出现异常而Crash掉。现在要讨论的主题就是与Tag1、Tag2的两处代码相关。一、关于del

3、etethis应用层创建和释放socket对象,而socket对象生命期由引用计数类托管,网络库在调用OnClose通知应用层socket句柄关闭的时候,socket对象开始做清理工作并递减引用计数,发现引用计数为0,进行deletethis(即“自杀”)。deletethis是一个”饱含争议“的操作,有认为It’susefull,也有认为It’sabadpractice,甚至有认为这是面试时唯一可以用来考验C++程序员的问题(TheBestC++InterviewQuestion–Ever!)。暂不管是usefull还是badidea,先来看dele

4、tethis的合法性问题(这里不讨论delete的语意,可以参考《InsideTheC++ObjectModel》)。C++Faqs中是这么阐述:只要你小心,一个对象通过成员函数请求自杀(deletethis)是没有问题的。下面是对“小心”的定义。1.你必须100%确定this对象是通过new分配的(而不是通过new[]、placement new、栈上局部对象、全局对象、或是另一个对象的成员)。2.你必须100%确定这个成员函数是this对象调用的最后一个成员函数。1.你必须100%确定这个成员函数余下的代码(deletethis之后)不会再访问th

5、is对象的任何一块内存(包括调用任何其他成员函数或访问任何成员数据)。2.你必须100%确定在deletethis之后,不再去访问该this指针。换句话说,你不能对它做检验操作,用来和其他指针比较(包括NULL),用来打印,做转换(cast)等任何操作。通常如果this指针指向的是一个不具有virtual析构函数的基类对象时往往会出现警告。既然deletethis有其合法性,我当且认为deletethis本身并非一个badpractice,而要看deletethis是否得当(这里我想起电影《钱学森》中的一句话:手上没有剑和有剑不用不是一回事。C++就是

6、这么一柄利剑,很多强大特性需要去权衡考虑用或不用)。正如人也会有自杀一样,有些是因为万千烦恼而自寻短见,有些则是舍身取义而自我牺牲,我们惋惜前者,敬佩后者。如果C++对象自杀能避免以上“忌讳”而达到了资源安全释放的目的,也就可以为之。二、堆破坏检测说完了deletethis,接下来要说堆破坏的问题。上面Tag2处的代码即犯了“小心”deletethis的第3条忌讳,OnClose触发应用层socket对象deletethis,而网络库却还在该对象的成员(m_hSock)进行写入操作,另外应用层还有别处在申请堆内存,结果发生堆破坏而造成程序Crash。堆

7、破坏是开发过程中常见的一个问题(尤其对于这种多人模块开发),可以借助PageHeap(页堆)工具来检测堆破坏。1、什么是页堆从Windows2000开始系统在堆管理器(即PageHeap管理器)引入“校验层”,该层处于Ntdll.dll模块内,可以验证程序所有的动态内存操作(分配、释放及其他堆操作)。当启用页堆管理器,让应用层序在调试器下启动时,如果遇到问题,调试器将会中断,但不指名是什么错误(如果不是在调试器下启动,则遇到问题只会崩溃而无任何反馈)。页堆有两种类型,正常页堆(NormalPageHeap)和完全页堆(Full-pageHeap)。完全

8、页堆:当分配一块内存时,通过调整内存块的起始分配位置,使其结尾恰好与系统分页边界对齐,然后在边

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。