今天终于让
脚本引擎可以成功执行int main(){return 1+1;}了,总算是让冒烟测试过了。一开始没那么顺利,主要是因为昨天写了一整天代码,犯了点错误。
举个例子,脚本里面有return语句,这个语句实际上是对应到一个jump指令去,跳到函数最后面执行一些代码然后返回。当代码生成执行到return的时候,实际上函数还没生成完,所以不知道jump到什么地方。因此我想到一个办法,我先把这些需要延迟填充的指令都记下来,当函数结束的时候一次性填充它们。于是我使用了下面的代码:
1 needToReturns.Add(&ins[ins.Count()-1]);
这样做我就把刚刚加入的那条jump指令,也就是当前的最后一条指令的指针添加到一个列表里面去了。于是我接着处理很多代码生成的工作,也免不了往needToReturns添加很多的其他jump指令。于是到了最后填充它们的时候了,没有问题发生。代码生成结束之后,我就要把再也不需要的符号表给析构掉,这个时候VC就报告说释放一个TypeInfo的时候完蛋了。
其实很明显,错误肯定不会出现在TypeInfo里面的,想都不用想肯定是哪里溢出了。但是自己的容器的operator[]都有溢出检查的,不可能通过a[b]=c;的方法导致内存出现错误。最后想来想去,发现问题出在上面那一行代码里。
我们都知道,一个列表在Add的时候,他所拥有的缓冲区肯定最终都会用光,然后分配一个更大的。于是之前的&ins[x]跟之后的&ins[x]的地址肯定不一样,于是我添加到needToReturns里面的引用就变成一个野引用了。搞定一个函数之后,我一下子填充它们,也就等于往各种各样不同的野引用里面写东西。刚好之后创建的一个符号表项就是某一个野引用指向的地方,于是内容就被我破坏了,释放它的时候当然就出现问题了。
这个故事告诉我们
1:永远不要试图获取容器中某一个项的引用。
2:就算是自己的类,有时候也会误用的。
关于我如何执行int main(){return 1+1;},可以在
Vczh Library++3.0的单元测试代码(UnitTest\UnitTest\TestScripting_BasicLanguage_CodeGeneration.cpp)里面找到。
posted on 2010-02-26 19:41
陈梓瀚(vczh) 阅读(2404)
评论(6) 编辑 收藏 引用 所属分类:
VL++3.0开发纪事