以后多用SAFE_DELETE

前些天羽毛汇报说那天杀的彩虹岛插件服务端又崩了。研究加壳过的程序崩掉后的dmp文件确实是个体力活。从eip来看程序是跑飞了,看了下esp处是个在dll领空内的地址,说明是call飞的,用这个地址减去dll的起始地址,然后用od加载错的dll,把刚才减出的偏移加到这个hmodule上,算是找到了出错的指令了,谢天谢地这段指令没有混淆过。这还没完,要根据这里的汇编码找出对应的源代码位置。。还算比较幸运,这个函数下面一个函数就有了字符串的引用,于是找到代码是OnDisconnect中delete m_session一句出错,从dump来看内存里已经不是SocketSession的内容了,应该是call析构函数call飞的,那么推断下来只可能是两种情况,要不就是哪里缓冲区溢出了,要不就是二次delete。我自己自然能保证我的代码中不会出现重复delete逻辑,但是OnDisconnect这个socket类库却不是我写的,天知道这个庞大的socket框架哪里又出了啥毛病,本来我已经为它改了N多bug了。。

然而如果是delete的问题,这个却不能说不能从我这里防止。因为多年来从vb混到.net,也就是代码一直是被托管着的,永远不会缓冲区溢出永远不会随便一个小问题就退出了函数调用都是微软的不用担心失败等等等等,使得我的程序一直在出错预防和处理上很糟糕,在正式做C++的project后,天啊。。

弄C++的应该都知道一个好习惯,就是free或者delete后立即赋值null,我写程序也不是不常用,只是有的时候记不住而已。

昨天弄D3D,在DXUT framework的dxstdafx.h中看到几个很有趣的宏

#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

在《DirectX 9.0游戏开发编程基础》中框架设计也有类似功能的代码,因为是D3D,似乎用的更多是com中的release。

如果说delete *p; p = NULL;这样写有点不好看的话用上面这个宏写出来貌似还是蛮帅的,嘻嘻。以后就用它了~~

DXUT里还有几个好玩的排错宏,比如V_RETURN等,我猜那个V应该是verify的意思。有机会写套自己的代码异常机制。这些日子真的是被那个dll各种稀奇古怪的bug给整疯了

Leave a Reply

Your email address will not be published. Required fields are marked *