在编程的世界中,只有你想不到的事情,懒的做的事情,没有做不到的事情。
曾经一度为使用哪种脚本嵌入游戏犯愁,lua 的源码过了几遍,python 的也看了点。lcc 也试过,还有 ch 什么的。真正用在项目里的就是 lua 和 python 了。我个人更偏好 lua 一点。越读它的 source code 越觉得它作为世界上最快的脚本语言,是名副其实。
很早以前,我觉得显示一个图片很难,好象发现很简单。曾经觉得汇编很难,结果发现很简单。曾经担心 C++ 太复杂学不会,现在已经感觉游刃有余了。还有学习 perl php 或者是 stl mfc 这样的库,不懂的时候都觉得难,懂了却是不过如此。
对于游戏,说什么掌握 3d ,网络编程,无非是些技术方向而已。肯花时间,一定没问题的。
这次是脚本虚拟机。已经想了很久了,怕太复杂需要投入过多时间和精力。可事实上,写起来却又一次发现不过如此。
上周五开始有这个念头的。自己实现脚本,一可以再享受一次编码的兴奋。二是自己实现的东西方便控制,想加什么加什么,想改什么改什么。语言也可以重新设计。三就是性能心里有底,看了那么多人家的实现,该怎么做好,也应该有数了。最后就是安全问题。网络游戏防外挂和逆向工程的问题,嘿嘿。估计是学术上为人鄙视,但我不得不重视的环节。
一开始我想用纯 C 做。不为别的,就是想练习一下 C 语言的功底。写了 1500 行程序,花了两天一晚。周日的时候,写到 gc 的部分就受不了了。对比以前写的 C 程序,感觉好了很多。但是比较自己的 C++ 代码,还是不够优美。一咬牙,C++ 重构。
到批昨天晚上,已经把先实现的东西弄完了。大约实现了基本逻辑,和堆栈,table ,函数等的支持,2000多行代码。最后 gc 模块写的比较顺利。用的标记整理算法。做的时候希望运行时减少一些大块内存移动。就在内部做了分页。原来以后是个小优化,后来为这个吃够了苦头。
晚上的时候, gc 完成,用 byte code 写了一个递归算阶程的小程序测试,并定义了函数嵌套。结果问题百出啊。最近几年写程序越写越顺,都有点飘飘然了。觉得自己编码几乎不会出错。腹稿一般都打的比较好。这次做设计也是腹稿打了很久,去年年末就在想实现了。酝酿到现在才动手写,觉得出了错也是小问题的。没想到,bug 折磨了一夜。
最初的问题来至于我对 byte code 本身的处理。byte code 我也设计成了 gc object 可以被回收和整理的。结果,一段被执行的代码也成了不稳定的东西,运行了一半,gc 跑起来,可能运行指针都飞了。后半截代码有可能不在原来的位置。这是现在发现设计考虑不成熟的唯一一个地方。解决了这个问题之后,就开始漫长的 debug 。
因为我是真正的内存整理的 gc ,所以的 gc object 都可能不在他们原来的位置,甚至任何一个虚拟机调用后,指针都会变的不可靠。而且监控内存很不方便。前面采用的分页整理害苦了我。而且第一页还是一个特别页,stack 会 share 一部分空间。这样虽然可以保证整个虚拟机跑在几大快内存上,绝对不产生任何内存碎片,但是 gc 代码异常复杂。
最近又比较累,半夜里头脑开始不清醒,只好到处加 assert。好在测试程序写的还可以,加的越多,新问题就越少。直到白天中午。才确保问题都被找到。
这次写这个东西,我悟到几个道理:
一个把 C 语言代码能写的非常优美的人,写 C++ 会更上一层楼。以后应该多多写纯 C 代码提高 C++ 功力。
熬夜写代码是兴奋的,但是熬夜调试复杂的程序,最好少干。
原理弄懂了,没有什么程序难写。但是原理自己悟的效果要好过看书。
下一步就是写编译器了 :)