有关new() T()

在看AngelScript文档的时候,讲到值对象构造函数和析构函数的注册,看到这样的内容:

void Constructor(void *memory)
{
  // Initialize the pre-allocated memory by calling the
  // object constructor with the placement-new operator
  new(memory) Object();
}

这里的new运算符有点怪哈,以前没见过,但只要不是傻子应该都能从上下文猜出含义。不过为了科学的严谨性,还是上网查了一下。这里就是不分配内存,而是直接在memory的地方进行构造。

顺便也把析构贴上。析构代码:

析构比较简单,直接调用析构即可。

void Destructor(void *memory)
{
  // Uninitialize the memory by calling the object destructor
  ((Object*)memory)->~Object();
}

反过来看为什么构造函数不是直接调用构造函数呢。我想应该还有虚函数表啊什么的一大堆乱七八糟事情要在构造函数前调用(事实上,好像有虚函数的类构造函数就是虚函数,至少分析彩虹岛的RTTI信息都是这样的)

参考文章:《new的六种重载形式》

http://dev.firnow.com/course/3_program/c++/cppjs/200827/99702.html

EDIT:用原来WP的插件插源代码指针符号总是会被变成>,下了个Source Code Formatter试试看~~

EDIT2: WLW会给Source Code Formatter的HTML代码自动换行,IE8会使换行也显示出来,要用兼容模式才能正常查看代码

放弃破解Rayman2的海盗头。。

整整三天的时间,最后闹个束手无策。。为三天假期表示沉痛哀悼。。

本来破解补丁已经写好了,通过Hook贴图的代码过滤掉海盗头和相关文字,正高兴着呢,结果上去玩两分钟就哭了。。Ubi太坏了,这招绝不是简单的贴个影响游戏的图就完了,游戏元素也会受到影响,本该潜水的鱼缸里没了水,悬崖峭壁的尽头少了紫色抓环。。

至此算是束手无策了,因为整个过程,从判定到检验到耍花招,所有的代码都是游戏地图编译脚本实现的,也就是说我们面对的是一堆无法理解的字节码,和一个不知道原理的脚本虚拟机。众所周知分析一个虚拟机程序意味着什么(VMP,给你做广告呢,别忘了给广告费~~)。更具体地说,Rayman2中脚本系统几乎占了全部的比重,也就是说x86代码只负责提供一个底层图形接口,任何有关游戏的东西全部由脚本实现,Ubi把文件改一改,还用Rayman2.exe就是另外一个游戏了(《麻烦大了》?Maybe?)

不过也并非一无所获,至少懂得了开发一个游戏,脚本系统的重量。相比之下彩虹岛果真垃圾的一塌糊涂了,貌似比wow占内存还多?

EDIT: (2010-8-5)
昨天又想到一个点子,是找到比对校验码的地方,强行相等,经过一下午搞,找到了突破口,但是很奇怪还是会出现CD-Missing,有点怀疑是程序校验了自己的代码段,最诡异的是如果用硬盘版在Whale关出CD-Missing的瞬间会崩溃,所以不能简单的屏蔽显示贴图能搞定的,另外就是16关那个反弹子弹打开通道的地方怎么也过不去,怀疑是游戏元素受到了影响。Win7下总是会出现各式各样的问题,XP下虚拟光驱就工作的很好。这下看来是真的没救了。

以后多用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给整疯了