<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[阿福的窝 - |兴趣+代码|]]></title>
<link>http://www.mega-zone.org/asp/pjblog2/</link>
<description><![CDATA[a fool&#39;s nest]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog2 v2.4]]></copyright>
<webMaster><![CDATA[()]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>阿福的窝</title> 
	<url>http://www.mega-zone.org/asp/pjblog2/images/logos.gif</url> 
	<link>http://www.mega-zone.org/asp/pjblog2/</link> 
	<description>阿福的窝</description> 
</image>

			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=489</link>
			<title><![CDATA[看了一堆]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Sun,26 Jul 2009 01:22:54 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=489</guid>	
		<description><![CDATA[从同事那边搞到一些动画，一口气看掉不少。<br/><br/>首先是<a target="_blank" href="http://en.wikipedia.org/wiki/Wicked_City_(film)">《Wicked City》（妖兽都市）</a>和<a target="_blank" href="http://en.wikipedia.org/wiki/Highlander:_The_Search_for_Vengeance">《Highlander: The Search for Vengeance》（高地人：复仇之旅）</a>，它们都是<a target="_blank" href="http://en.wikipedia.org/wiki/Yoshiaki_Kawajiri">Yoshiaki Kawajiri</a>导演的作品。其实这个导演我也不认识，看了这两部动画之后才去搜了一些资料。原来Animatrix系列中的那部<a target="_blank" href="http://whatisthematrix.warnerbros.com/rl_cmp/animatrix_frames_program.html">《Program》</a>也是他导演的。这些片子的风格很相近，主角都是硬派猛男+实力美女，在战争中穿插爱情，带有一丝悲剧色彩。个人还是最喜欢Animatrix中的那部短片～～<br/><br/>然后开始看一部号称灰色成人童话的<a target="_blank" href="http://zh.wikipedia.org/w/index.php?title=奇諾之旅&amp;variant=zh-cn">《奇诺之旅》</a>，很短，只有13集。观赏了前几集，都是一个一个的小故事，片子似乎想在平淡的叙事之中融入一些深刻的寓意，只是动画的背景设定实在有点太古怪，所以暂时木有继续。<br/><br/>最后是<a target="_blank" href="http://zh.wikipedia.org/w/index.php?title=Macross_Zero&amp;variant=zh-cn">《Macross Zero》</a>，这部一直想看的电影终于被我搞定了。不剧透了，总体感觉和大部分观众一样，有点神棍啊～～不过空战还是拍得相当帅的，尤其是在我迷恋上Ace Combat系列之后，看起来分外有感觉啊。<br/><br/>嗯嗯，相当有收获～～]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=475</link>
			<title><![CDATA[桌游的基本原则]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Thu,25 Jun 2009 00:08:49 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=475</guid>	
		<description><![CDATA[今天又玩了一盘《冰与火之歌》，带扩展共6人，因为有2新人参与，所以进行的比较慢。但第三回合的时候出现了一个意外情况，白方迅速南下，抢占了第五个城池，即将有机会结束游戏并获胜。我执黑，当时我可以先行将白方的一个城攻下，让它无法结束游戏。<br/><br/>牌面上战况比较明朗，红方刚刚被我打到元气大伤，处于非常不利的地位。我将要进攻的这个白方城池，可以接受红方的support。如果没有support，则我必可以将其攻下。<br/><br/>红方可以选则support我，但没有实际意义，因为我自己的兵力足够。于是红方向我询问是否需要support时，被我谢绝。我考虑我们双方其实处于交战状态，没有必要做这种无意义的结盟。结果红方居然选择去support白方，导致我进攻失败，进而白方顺利占领6个城池，游戏结束。<br/><br/>最终，白方获胜，其他人都输掉了游戏。<br/><br/>我觉得这个过程非常有意思，这和我以前一直考虑的桌游基本原则有关。桌游的参与者如果没有遵循一些基本的原则，将导致游戏进程变得大不一样，甚至改变游戏的平衡。<br/><br/><strong>首先是求胜的原则。</strong>在很多桌游的设定中，只有一个赢家，其他人都算输家。这个时候我觉得所有参与者都应该最大限度的谋求自己的胜利，而不是去帮助其他玩家获胜。当然会出现一种情况，那就是某个玩家陷入无法获胜的局面。<strong>这个时候保持中立非常重要，否则失势的弱者如果盲目依附于某一方，必然会造成游戏平衡的破坏。</strong><br/><br/>但游戏总是人在操作，如果自己无法获胜，那很难再揣测这名玩家的行为。因为游戏规则内的唯一奖励就是获胜，如果无法得到，那么只好退而寻求其他方面的乐趣——比如报复和扰乱行为，这的确也能带来一些乐趣：）<br/><br/><strong>其次是能否撒谎的原则。</strong>除去一些专门的谎言游戏，很多桌游的沟通都带有谈判性质，玩家可以达成某项协定，然后影响游戏决策。但是否可以先达成协议，然后在实际行动中反悔呢？因为协议往往五花八门，没有详细的规则约束，只是口头的。我个人倾向于不允许撒谎，即达成的约定必须履行。<strong>如果没有沟通的意愿，可以拒绝提议或者保持沉默。</strong><br/><br/>很多人都觉得这样丧失了游戏的乐趣，但我一直比较反感在重策略的游戏中加入撒谎的元素——顺道一提，这也是我不喜欢杀人游戏的原因。撒谎可以认为是一项技能，我也承认我不善于撒谎，但我们是不是需要在每一个可以运用这项技能的地方都去施展一下它？<br/><br/>很多桌游被设计成规则主导的一种活动，表现为玩家通过各种游戏动作互相制约。但撒谎会让很多规则变得不可捉摸，甚至弱化了很多规则，最终让大部分游戏都沦为口舌之争——行动上的策略变得不再重要，因为大家都围着一张桌子，你只要骗过你的对手就可以获得胜利。<br/><br/>如果非要认为玩游戏也得锻炼什么的话，我觉得大可以不必锻炼这种能力，至少不必在每种游戏里都锻炼骗人的能力：）<br/><br/>所以，这些基本的原则在游戏之前一定要商量好，否则只好“不惮以最坏的恶意来揣测对手”，才能有机会获得胜利。<br/><br/>BTW：很想扯一下最后这个决策失误的问题，很早以前我遇到过类似的情况。记得那是在学校的某次xx选举中，某关系一般的同学A突然跟我说，要不我投你一票？我当时比较自信，而且A坦言不喜欢另外一个比较有竞争力的候选人，再加上我也不想搞什么拉票行为，基于这种莫名其妙的约束感，就很随便的说了句“无所谓啊，你自己看吧。”于是A同学很失望的离开。最终投票结果让我完全orz，只差一票，被另外一人当选。然后A同学得意的跟我说，我没投你投了另外一个人，怎么样后悔了吧。<br/><br/>类似的场景不是么？我总是尽可能的谢绝无谓的帮助，因为我喜欢独立的感觉，不喜欢依赖。但在某些竞争条件下，看似无谓的帮助其实并不是真的无谓，它如果加到对方的头上，那么对自己就是不利的影响——因为我们无法强求第三方做到中立。<br/><br/>总之，看问题还是得全面一些呐 <img src="http://www.mega-zone.org/asp/pjblog2/images/smilies/Baozi\009wopei.gif" border="0" style="margin:0px 0px -2px 0px" alt=""/>]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=473</link>
			<title><![CDATA[妙哉]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Sun,21 Jun 2009 21:07:16 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=473</guid>	
		<description><![CDATA[<div class="UBBPanel"><div class="UBBTitle"><img src="http://www.mega-zone.org/asp/pjblog2/images/code.gif" style="margin:0px 2px -3px 0px" alt="程序代码"/> 程序代码</div><div class="UBBContent">typedef char Small;<br/>class Big { char dummy[2]; };<br/>Small Test(U);<br/>Big Test(...);<br/>T MakeT();<br/><span style="color:red">const bool convExists = sizeof(Test(MakeT())) == sizeof(Small);</span><br/></div></div>（摘自《Modern C++ Design》）<br/><br/>利用形如这样的代码来侦测继承关系，简直是妙绝！<br/>看来，c++更适合作为娱乐大脑的玩意儿。]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=465</link>
			<title><![CDATA[所谓版本]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Sun,07 Jun 2009 04:51:10 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=465</guid>	
		<description><![CDATA[一个使用c++开发的wn32程序，用msvc来编译，可以折腾出多少个版本呢？下面来分析一下。<br/><br/>首先，debug和release两个版本的区别是最常见的。debug版一般会定义类似_DEBUG的宏，优化关掉，编译同时输出debug信息。release版则一般会定义类似NDEBUG的宏，编译优化选项打开，同时不输出debug信息。<br/><br/>然后是字符集的区别，可以选Unicode版，也可以使用Multi-Byte版。前者一般会定义类似_UNICODE这样的宏，使用wchar_t处理字符串，后者则是用char来作字符串处理。貌似c标准库里面的绝大多数字符串函数可以通过包含&lt;TCHAR.h&gt;来做到一份代码通吃两个版本，但对于c++的标准库就没有这么现成的东西了，还是得显示的指出究竟用std::string还是std::wstring。自己定义一份tstring也可以，不过什么cout,stringstream统统都得来一份t版。<br/><br/>接下来是run-time的选择，VS提供了/MT和/MD两种编译选项，分别代表静态链接到标准库和动态链接到标准库。各有什么优劣俺也不是十分清楚，但链接到第三方提供的lib时，经常会出现符号重定义的链接错误，往往是这里的问题。<br/><br/>以上三种编译选项都是独立的，所以我们可以得到2^3 = 8种版本的程序。是不是感觉很high哦？<br/><br/>还没完……如果你是写一个lib，这里会多一个选择。你的lib将以静态库的方式还是动态库的方式提供？算上这种选择，就有2^4 = 16个版本。<br/><br/>很爽吧。啥叫自由度？这就是自由度。]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=455</link>
			<title><![CDATA[战神是如何炼成的]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Sun,17 May 2009 02:54:39 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=455</guid>	
		<description><![CDATA[自打《胧村正》入手108把刀之后，屋子里的电视又成了摆设。说起来这个电视机有个令人十分不爽的地方，就是它始终会显示当前的频道。如果我切换到AV端子，那么左上角就会写着“AV1”几个红色的字。切换到S端子，就显示“AV2”。在我玩游戏的时候这几个字特别碍眼，我超想把它们去掉，但怎么调也找不到可以去掉这几个字的选单。所以，《胧村正》算是一边看着AV一边打穿了的。<br/><br/>今天起床之后，不知怎么就打开了电视机。看到那个红色的“AV”字样我很不爽，拿起遥控一阵乱按。正好在&#34;Menu&#34;键上多按了几秒，结果电视里出现了一个从来没见过的菜单。翻了一下里面有个“Status”项，我尝试着选成“Hide”——电视机泪流满面，&#34;AV&#34;不见鸟=_=<br/><br/>这个电视的牌子貌似是什么&#34;JINXING&#34;，应该是祖国产品。我太佩服设计遥控器的人了，居然有&#34;长按&#34;这个动作。遥控器上本来已经二三十个按键了，多加一个会死么，非得靠长按来切换，太有想像力了。<br/><br/>不管怎么说，AV木有了，顿时心情大好，决定开始攻略战神。战神是在入了PS2不久就开始玩的，结果到了某个可以滚动的房间之后，碟片读取失败导致不能继续。后来借了同事的碟片往后玩了一小段，然后因为乱七八糟的事情放下了。碟片还掉之后没有再玩，今天索性不管了，拿出我的有问题的碟片，战神Restart！<br/><br/>一口气玩到最后一关，碟片很给面子，再没有出现不能读的情况。但是这最后一关实在令我很不爽，关卡的设计有赶工的嫌疑。首先是很长时间没有boss，都是杂兵战，让人打得提不起精神。特别值得一提的机关是某个带刀刃的柱子，要从下面爬上去。柱子还不短，爬的挺无聊的，就是得躲上面的刀刃。但是一个不小心碰到刀刃掉下来，就得重新爬。反反复复十几次，摔手柄的心都有了。<br/><br/>好不容易爬过去，再玩一小段就遇到了最终boss，我于是很期待一场大战。第一场战斗还不错，变成巨人的奎秃和前战神单挑。不过战斗很短，QTE也只有一个，让我非常不过瘾。<br/><br/>打完之后场景切换，奎秃的妻儿出现，要求保护她们不被杀死。这次成堆的小兵开始刷出来，只打女人和小孩，就是不和奎秃打。奎秃对小兵的攻击基本没法让它们硬直，于是小兵对着女人孩子照砍不误。我反反复复玩了十几回，每次拼命砍杀了半天还是女人和小孩先没血了……摔手柄的心情再次出现。<br/><br/>后来找视频攻略看了才发现，奎秃要一上来就变身，变身之后狂放魔法。被杀掉的小兵正好可以再次补满气槽，于是很快再次变身狂放魔法，解决战斗……知道方法之后，整个过程就变得很无聊，半分钟搞定=_=<br/><br/>接下来boss战第三场开始，奎秃的武器都被拿走，系统强制给换了一把出招和收招都很慢的大剑。我整个游戏辛辛苦苦练出来的武器就这样都消失了。最不能让人接受的设定是boss和奎秃的血槽共享，也就是说，如果boss对着奎秃放上几招，奎秃没血了不说，boss的血居然还能加回来。<br/><br/>我从来没见过这么无聊的最终boss战，整个过程就是一个字——跑！因为boss的招术都很霸道，一打中就伤很多血，再加上共享血槽的设计，相当于前面砍掉的部分都白搭了。手头的武器出招巨慢无比，这个整个游戏从来都没有出现过的武器就这样强加给玩家，让我觉得我仿佛是在玩另外一个游戏。<br/><br/>其实打法很简单，就是利用boss的某个明显的破绽，抽空上去狂砍，理论上讲两次就能砍掉boss。关键就是这个带破绽的招术boss不一定会出，半天没出的话，过程中再被boss打上几下，boss的血吸得比刚开始还多，不如重打。如此反反复复又是十几遍，在我几乎就要把手柄摔在电视机上的时候，终于赶上boss犯傻，被我砍翻。<br/><br/>战神的最终关卡设计的如此没有感觉，让我很奇怪。基本就是在重复某个机械过程，操作步骤其实是一眼就被看穿的，游戏强制你一遍一遍的玩，直到足够熟练。内容跳跃的很厉害，我在前面游戏过程中的积累都没有能够在最终boss战中应用，莫名奇妙的就结束了。<br/><br/>不过总归是结束了，总体来说《战神》还是很赞的，画面和关卡（除了最后一关）都很吸引人。等有空再继续《战神2》吧……希望不要再出现让我想摔手柄的设计了。<br/>]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=449</link>
			<title><![CDATA[战啊]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Fri,17 Apr 2009 01:04:12 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=449</guid>	
		<description><![CDATA[最近玩街霸4比较上瘾，有点找回当年街霸2的感觉。上一作的街霸3是1999年的作品，时隔10年街霸重新登场，这执着让我很感动。不过系统上变化很大，当年2的影子基本上看不到了，据说和3的系统更相似，我没玩过3所以不好评价。<br/><br/>玩了好几天，爽得很——我是说被电脑虐得很爽。发现和公司里面格斗达人差距太大，操作的时候无谓的动作很多，也木有多少战术。唉，其实格斗游戏的思考量也不小呢。当初就知道乱打，一直是随机放招的水平。现在也终于能小连几下了，打得稍微有点章法。抽空还重温了当初YS同学发给我的街霸3精彩视频，看得热血沸腾，甚至有了找来街霸3玩一玩的冲动。<br/><br/>不得不说的是，今天终于让我发现了very easy模式之下还有easiest模式，于是一口气把6个隐藏人物打了出来，很痛快啊。话说街霸4设置了8个级别的难度，我只能在最简单的混一混，望天……目前还是觉得Ryu和Cammy最想研究，Sakura也不错。但是以摔投技为主的角色还是一个也不会用，过去就被打死了，唉……<br/><br/>这几天真是战斗不断呐～战吧战吧～～！]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=444</link>
			<title><![CDATA[我爽]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Wed,25 Mar 2009 02:25:27 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=444</guid>	
		<description><![CDATA[修了一个该死的bug，折磨我好几天了。<br/><br/>这个bug比较傻，大概是由于DX用久了来到OGL的世界有点不习惯，于是把投影矩阵的参数设置了几个很诡异的值。其一是近剪裁平面我居然设置了一个负数，其二是fov我传了一个弧度值，而OGL的参数单位是角度。之所以搞了我大半天主要是这bug表现太诡异了，而我又总是胡思乱想，毕竟对OGL不熟=_=b<br/><br/>首先表现为转动模型的时候，在某个角度会出现后面的面片挡住了前面的面片，而某些角度又是没问题的。这导致我一直以为是z-fighting或者是depth test出了问题。后来关闭了back-face culling才发现其实所有角度都有问题……然后考虑了半天，终于发现了近剪裁平面设置了负数，马上改了一个正数以为就好了。<br/><br/>结果又出现了更诡异的表现：无论我怎么调整ModelViewMatrix，模型始终画在很近的地方，而且巨大无比。让我又开始怀疑是自己的camera或者模型的变换矩阵设置的有问题，结果左查右查终于灵光一现，发现OGL的fov不是弧度是角度……<br/><br/>囧啊，不仔细看文档上来就写的后果就是这样滴 <img src="http://www.mega-zone.org/asp/pjblog2/images/smilies/Baozi\013baohan.gif" border="0" style="margin:0px 0px -2px 0px" alt=""/>不过也许还和我深夜精神状态比较飘忽有关系，看起来挑个更好的时间coding才是正道。<br/><br/>总之是修掉了这个巨傻无比的bug，哈哈！]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=440</link>
			<title><![CDATA[穿掉了《战争机器》]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Sun,15 Mar 2009 03:54:54 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=440</guid>	
		<description><![CDATA[和室友一口气打穿，居然玩了8个小时。太投入了=_=不愧是Epic的当红名作，完全没有一丝拖沓。Fire，Reload，Move On……如此这般直到最后～<br/><br/>最近玩过的一堆FPS里面，除了Call of Duty 4，当属Gear of War来劲。而类似Crysis或者FarCry这种，完全不是我期望的风格。就更不用提《Lost Planet》之类的。倒是对《F.E.A.R》很感兴趣，有空可以试试这个。<br/><br/>顺道总结出一个规律，凡是叫做《xxx of War》的游戏一定差不了。比如《God of War》，比如《Dawn of War》，再比如这个《Gear of War》。都是神作啊～<br/><br/>推荐<a href="http://shooting.mega-zone.org/" target="_blank">shooting</a>同学试试看～]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=133</link>
			<title><![CDATA[ID3DXSprite的效率问题]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Sat,17 Jan 2009 00:26:57 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=133</guid>	
		<description><![CDATA[两年半之前，具体的说是这个时间：“2006-07-02 05:27:28”。那会儿我还在折腾传说中的RTG——俺们的一个小demo。我折腾的如火如荼，觉也不睡，饭也不吃，最后挖了个坑就没后话了。后来我就想写点东西，记录一下开发过程中我使用DX提供的ID3DXSprite的痛苦经历，题目就叫做《ID3DXSprite的效率问题》。<br/><br/>憋了半天，最后只写出一个“啊”字，然后两年半就这样过去了。现在又翻出了草稿，看着那个“啊”字，想想其实也没啥好写的，无非就是要说这么一件事情：<br/><br/>ID3DXSprite，那是相当的慢啊。<br/><br/>当初我是在某论坛上看到一个人用非常老道的口吻说：不要觉得ID3DXSprite这个接口慢，你自己实现还不一定比它快呢。于是想也不想就拿来用了，后悔的很。其实，这话反过来说倒是挺对的。<br/><br/>再也不迷信了。<br/>]]></description>
		</item>
		
			<item>
			<link>http://www.mega-zone.org/asp/pjblog2/default.asp?id=432</link>
			<title><![CDATA[Singleton和析构顺序]]></title>
			<author>(FantasyDR)</author>
			<category><![CDATA[|兴趣+代码|]]></category>
			<pubDate>Fri,16 Jan 2009 23:55:48 +0800</pubDate>
			<guid>http://www.mega-zone.org/asp/pjblog2/default.asp?id=432</guid>	
		<description><![CDATA[今天遇到的这个问题很有代表性，查了半天终于解决了。然后又仔细分析了一下前因后果，觉得应该搞清楚了，那末记录下来……<br/><br/>问题出在我自己写的一个小游戏程序。程序是用了DirectX的SDK提供的DXUT作为应用程序的框架，因为自己懒得去折腾什么Device Lost和Windows的消息循环了，能用现成的便用之。错误出在退出的时候，报错说D3DDevice的引用计数没有清零。<br/><br/>于是乎开始检查什么地方AddRef之后没有Release，搞来搞去觉得没有问题，因为一直是成对写的。然后就考虑是不是有什么地方没有调用到，或者多次调用了。再次查了半天，设置了几个断点，发现果然有Release的地方没有被调用，具体讲起来是某个singleton的LostDevice方法。<br/><br/>这个方法被我放在了DXUT提供的一个负责处理LostDevice的callback里面，我把断点加在这里，显示这个callback确实被调用了。代码大致就是这个样子：<br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.mega-zone.org/asp/pjblog2/images/code.gif" style="margin:0px 2px -3px 0px" alt="程序代码"/> 程序代码</div><div class="UBBContent"><br/>void CALLBACK HandleLostDevice()<br/>{<br/>&nbsp;&nbsp;Singleton::GetInst()-&gt;LostDevice();<br/>}<br/></div></div><br/><br/>但是再跟进去，发现虽然singleton的LostDevice也被调用了，却没有执行到真正的LostDevice方法，而是执行了singleton父类实现的方法。因为这个LostDevice()是一个virtual function，我在子类中写了其他的实现，现在却没有调用，所以出现引用计数的错误。<br/><br/>百思不得其解，单步跟进去确实走到了GetInst()里面，这里的实现大致是这样的：<br/><br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.mega-zone.org/asp/pjblog2/images/code.gif" style="margin:0px 2px -3px 0px" alt="程序代码"/> 程序代码</div><div class="UBBContent"><br/>class Singleton<br/>{<br/>public:<br/>&nbsp;&nbsp;static Singleton* Singleton::GetInst()<br/>&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;static Singleton inst;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return &amp;inst;<br/>&nbsp;&nbsp;}<br/>}<br/></div></div><br/><br/>还好Visual Studio很好很强大，继续看inst的成员，好像都被清空了，紧接着突然发现它的vftable居然填写的是父类的vftable，而不是自己的……怪不得LostDevice会调用到父类上面去。<br/><br/>但是如果vftable出错，那么刚开始就应该出错了，重新运行程序加断点发现除了退出的时候，其余时候vftable的内容都是正确的。然后就开始考虑退出的时候会发生什么……析构……<br/><br/>看这个callback的调用堆栈，果然是在某个对象的析构函数里面调用的。再找这个对象的定义，原来这个对象也是DXUT里面的一个singleton，实现方式和我这里的大同小异，也是储存在GetInst()这类方法的静态变量上。<br/><br/>接下来就没有细想，就觉得应该是析构顺序的原因。DXUT的这个singleton的构造时间的应该比我用到的那个singleton要早，所以析构的调用就会晚一些，它在析构里面又尝试使用我的singleton，会发生什么？<br/><br/>一时想不清楚，但总归这样是不对的，使用一个已经析构掉的singleton算啥？让死人重生么？于是我修改了我这边singleton定义，把它变成了这样（只写了关键部分）：<br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.mega-zone.org/asp/pjblog2/images/code.gif" style="margin:0px 2px -3px 0px" alt="程序代码"/> 程序代码</div><div class="UBBContent"><br/>class Singleton<br/>{<br/>public:<br/>&nbsp;&nbsp;static Singleton* GetInst() {return &amp;s_Inst;}<br/>private:<br/>&nbsp;&nbsp;static Singleton s_Inst;<br/>}<br/>Singleton Singleton::s_Inst;<br/></div></div><br/><br/>static成员变量应该会早于函数内的static变量，先被构造出来。因为我记得函数内的static变量是在函数第一次被调用的时候构造出来的。实现好之后重新运行，尝试退出，发现问题解决了。LostDevice方法这回被调用到了。<br/><br/>回家的路上一直在考虑那个错误的vftable，为什么会弄出父类的vtable啊。到家之后查了半天，没有找到直接的说法。然后看到有文章写不要在构造或者析构函数里面调用virtual function，一下子明白了。<br/><br/>我原以为我的singleton先被析构之后再次被使用的话，调用GetInst()的时候会重新构造一个出来。实际上并没有发生第二次的构造，再次使用的时候，用的就是析构之后的static变量。而含有vftable的对象在析构的时候，会把vftable一层层的退化到父类。这是因为如果父类的析构函数中调用了virtual function，而vftable还是子类的，那么就会调用子类的方法。而父类的析构是在子类析构之后发生的，这时最安全的假设就是子类的数据全部不存在了，也不应该调用子类的virtual function，所以vftable会被置成父类的。<br/><br/>如此一来就出现了很多文章告诫人们不要在c++的析构函数里面乱调virtual function，除非你知道自己在干什么，这和c#或者java的实现不一样。构造函数中也类似。而我就被这诡异的机制坑了一把，得到了一个很莫名其妙的错误表象。<br/><br/>总结一下就是，singleton这个东西，一定要明确它什么时候诞生，什么时候消亡，是不是真的只有一个。第二个就是千万不要在析构里面调用virtual function。说起来DXUT在它实现的singleton的析构函数里面居然调用了一个暴露给用户的callback，这其实和调用virtual function是一个道理，所以这次的错误也要算微软一份 <img src="http://www.mega-zone.org/asp/pjblog2/images/smilies/Baozi\032huaiyi.gif" border="0" style="margin:0px 0px -2px 0px" alt=""/>]]></description>
		</item>
		
</channel>
</rss>