最近写的模块,在独立的应用程序中测试是没问题的,但把它装配成DLL后,再在另一个应用程序中调用时却出现了内存错误。程序的模块链接关系大概是这样的: module就是我所写的模块,在这里被封装为DLL,因为要使用json相关的功能,该DLL链接了一个静态库 (jsoncpp.lib)。最后在应用程序中导入并使用module.dll,同时因为在应用程序中也需要用到json,所以应用程序也链接了jsoncpp.lib。 以下用一些伪代码来描述这些模块间的调用关系,以具现出这个错误。 jsoncpp.lib为c++提供了功能齐全的json操作,其核心的类是Json::Value。(阅读本篇文章你无需了解太多json) module.dll中导出了一个接口: //ModuleClass.h #include "json/value.h" #if defined MODULE_EXPORTS #define MODULE_EXPORTS __declspec(dllexport) #else #define MODULE_EXPORTS __declspec(dllimport) #endif class ModuleClass { public: MODULE_EXPORTS void AllocSomeMemory( Json::Value &root ) { // 这将申请一些内存,因为会new出一个Json::Value,并append到root上 root.append( "testString" ); } }; 应用程序: #include "json/value.h" #include "ModuleClass.h" int main() { Json::Value root; ModuleClass::AllocSomeMemory( root ); } 在Debug模式下,当main函数执行完毕,对Json::Value root进行析构时,程序便出现了异常。分析下,很显然,调用ModuleClass::MallocMemoryHere时申请的内存,是在module.dll中申请的,而对这些内存的析构则是在应用程序(.exe)中进行的(析构root会同时析构append在root上的所有子Json::Value)。不过,这是异常的真正原因么? 追踪到异常的出错点:dbgheap.c文件中那句ASSERT语句。 [...]
第一次听说online course是同事给我推荐的MIT的讲algorithm的课程,随后自己上youtube看了几集,真是大赞。并不是说崇洋,而是国外的老师确实讲得好,条理清晰,而且不乏个人风格,幽默风趣。更难得的,计算机的课程他们居然都是全部只用黑板,而很少用slides。并不是说slides不好,而是他们不像国内的老师,讲课通篇都是过PPT,发催眠曲。online course真是个好东西,让我们这些土鳖能够不用留洋就能感受到国外计算机的课程,况且还是像MIT,Stanford这样的名校。通过这些课程,不仅能领略到国外老师的风采,还能学英语,因为如果听不懂,有些课程还配置了整个课程的transcript,真是非常优质的学习材料。 不过这些课程,对于我这样的已经走出学校的人来说,只能粗看感受一下精华了,不可能真的跟着课程一集一集的细嚼慢咽,已经过了全额学习的那个时期了,要是早几年在大学里能发现这样的材料就好了(或许那时候也没有)。 http://see.stanford.edu/see/courses.aspx Stanford的关于computer science的课程,课程不多,但都非常详细完整的提供了video, handout, assignment, transcript,甚至还有考试试题和答案。 http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/ MIT的,课程很丰富,但只有部分提供了video,推荐Introduction to Algorithms.
1. 使用db2cc命令启动db2 control center时出现 – Error: Can’t connect to X11 window server using ’0.0′ as the value of the DISPLAY 解决方法: – su root – xhost + 关于xhost: http://linux.about.com/library/cmd/blcmdl_xhost.htm 2. 使用control center操控数据库时抛出SQL4414N错误 解决方法: – su dasusr1 – db2admin start 3. 在用db2move导出数据库时出现如下的错误 Application code page not determined, using ANSI codepage 1208 Error opening list file. Terminating [...]
在这次找工作的过程中,有一道笔试题让我印象深刻,题目只有简单的一句话:please use pseudo code to write a game engine framework(请用伪代码写出一个游戏引擎的框架) 当时看到这道题,完全是一种头皮发麻的感觉,虽然我对游戏引擎还算比较熟悉,但它可是个“巨象”般的庞大结构,要在短短的90分钟的笔试时间内把它“摸”完(而且90分钟也不只这一道题),那可真是天方夜谭。所以我当时在试卷上留下的结果就是,草草的画了几个模块图了事。 之后我才意识到,我根本就完全没有理解这道题,或者说,是完全没有理解一个词的意义——framework。受游戏引擎庞大印象的牵连,我把framework想得太大了。 Framework对于IT人士来说貌似是个挺时髦的词,这个词也经常被我们挂在嘴边,我也如此。但问题是,我几乎从来没有去好好的留心过或者深究过,到底什么才是framework,什么样一个东西才能被称为framework,它的准确定义又是什么呢。 看一般英汉字典里对于framework的解释: structure giving shape and support 框架; 结构 这只是给了我们framework的中文翻译而已,几乎还是没有给我们什么有用的信息。 记住一句话:有困难,找Wiki。当我看到Wiki上对software framework精确的定义时,突然间,一切都明白了。 原文URL:http://en.wikipedia.org/wiki/Software_framework A software framework, in computer programming, is an abstraction in which common code providing generic functionality can be selectively overridden or specialized by user code providing specific functionality. Frameworks are [...]
最近在读这本Robert Martin的Clean Code,中文译本是《代码简洁之道》,我觉得非常好看。我一直比较注重写出简洁出色的代码,并且一直以为自己在这方面做的还不错,但随着这本书的阅读,虽然我的一些观点和想法被得到验证,但另外一些却完全被颠覆。也让我意识到离一个出色的专业程序员还有多大的差距。 We’ve all looked at the mess we’ve just made and then have chosen to leave it for another day. We’ve all felt the relief of seeing our messy program work and deciding that a working mess is better than nothing. We’ve all said we’d go back and clean it up later. Of [...]
上图是通过Instancing渲染了10000个低精度模型(低于200个面),有skin动画,但是人物没有AI。在实验室Geforce 8800GT的显卡上fps可以跑到80帧。 接着,我给人群加上点简单的AI,每个人物进行向一个目标点移动,于是我在每帧更新的时候添加了如下的这些代码。代码中,MeshInstance是instance的类,对应于一个人物实例,Move是移动人物实例的简单AI函数。对于所有的Instancing数据,我使用一个vector列表存储——m_vpInstancingData。代码通过vector的iterator(迭代器)遍历所有的instance,对每个instance执行Move函数。 for( vector< MeshInstance* >::iterator i = m_vpInstancingData.begin(); i != m_vpInstancingData.end(); i ++ ) { ( *i )->Move(); } 结果,加上这段代码之后,程序的效率居然骤降,如下图,fps只剩下44帧。这让我很是纳闷,因为在加上代码之前,CPU基本上是空闲的,因为所有的骨骼蒙皮+渲染全部都是GPU扛着,而在CPU加上一个10000次的for循环后,整体效率大打折扣。它的杀伤力有这么大么……CPU不太可能这么低能。 然后,我把(*i)->Move()这行代码注释掉了,仍然只有40多帧,即一个只是10000次的空for循环,仍然是效率的瓶颈,10000次的Move根本不是问题。 难道是迭代器在影响效率?于是把代码改成了下面这样,不用迭代器遍历vector,而直接使用数组形式访问vector来遍历。 for( int i = 0; i < NUM_INSTANCE; i ++ ) { m_vpInstancingData[i]->Move(); } 再次执行之后,fps又回归80帧!! 对于vector的遍历,一直以来一直都是通过迭代器遍历,但对于大型vector它居然会如此的影响效率,也是到今天才刚发现。但是STL的设计本来就是奔着方便高效的啊,迭代器不至于效率影响这么大吧,可能与Debug模式有关。于是,我做了一个小实验,代码如下。 #include <iostream> #include <vector> #include <time.h> using std::vector; using std::cout; using std::endl; #define MAX_NUM 1000000 [...]
今天遇到一诡异的Bug,在某段代码之后,只要一执行vector的push_back函数,就报出异常——std::bad_alloc。 bad_alloc?这一般是new申请内存不足而扔出的异常么,内存耗光?绝对不可能。 折腾了很久,最后发现的错误根源是如此的愚蠢。 对于类的一个成员变量 QuadNode *m_pChild[4],我对它的初始化居然是这样的: ZeroMemory( m_pChild, sizeof( QuadNode ) * 4 ); 很显然,sizeof( QuadNode )绝对是大错特错,因为m_pChild是一个指针数组,而不是QuadNode的数组。 其实这个错误不值得拿出来一说,只不过是Bug所表现出来的症状有些奇特,所以留文以作警示。