今天終于讓
腳本引擎可以成功執(zhí)行int main(){return 1+1;}了,總算是讓冒煙測(cè)試過了。一開始沒那么順利,主要是因?yàn)樽蛱鞂懥艘徽齑a,犯了點(diǎn)錯(cuò)誤。
舉個(gè)例子,腳本里面有return語句,這個(gè)語句實(shí)際上是對(duì)應(yīng)到一個(gè)jump指令去,跳到函數(shù)最后面執(zhí)行一些代碼然后返回。當(dāng)代碼生成執(zhí)行到return的時(shí)候,實(shí)際上函數(shù)還沒生成完,所以不知道jump到什么地方。因此我想到一個(gè)辦法,我先把這些需要延遲填充的指令都記下來,當(dāng)函數(shù)結(jié)束的時(shí)候一次性填充它們。于是我使用了下面的代碼:
1 needToReturns.Add(&ins[ins.Count()-1]);
這樣做我就把剛剛加入的那條jump指令,也就是當(dāng)前的最后一條指令的指針添加到一個(gè)列表里面去了。于是我接著處理很多代碼生成的工作,也免不了往needToReturns添加很多的其他jump指令。于是到了最后填充它們的時(shí)候了,沒有問題發(fā)生。代碼生成結(jié)束之后,我就要把再也不需要的符號(hào)表給析構(gòu)掉,這個(gè)時(shí)候VC就報(bào)告說釋放一個(gè)TypeInfo的時(shí)候完蛋了。
其實(shí)很明顯,錯(cuò)誤肯定不會(huì)出現(xiàn)在TypeInfo里面的,想都不用想肯定是哪里溢出了。但是自己的容器的operator[]都有溢出檢查的,不可能通過a[b]=c;的方法導(dǎo)致內(nèi)存出現(xiàn)錯(cuò)誤。最后想來想去,發(fā)現(xiàn)問題出在上面那一行代碼里。
我們都知道,一個(gè)列表在Add的時(shí)候,他所擁有的緩沖區(qū)肯定最終都會(huì)用光,然后分配一個(gè)更大的。于是之前的&ins[x]跟之后的&ins[x]的地址肯定不一樣,于是我添加到needToReturns里面的引用就變成一個(gè)野引用了。搞定一個(gè)函數(shù)之后,我一下子填充它們,也就等于往各種各樣不同的野引用里面寫東西。剛好之后創(chuàng)建的一個(gè)符號(hào)表項(xiàng)就是某一個(gè)野引用指向的地方,于是內(nèi)容就被我破壞了,釋放它的時(shí)候當(dāng)然就出現(xiàn)問題了。
這個(gè)故事告訴我們
1:永遠(yuǎn)不要試圖獲取容器中某一個(gè)項(xiàng)的引用。
2:就算是自己的類,有時(shí)候也會(huì)誤用的。
關(guān)于我如何執(zhí)行int main(){return 1+1;},可以在
Vczh Library++3.0的單元測(cè)試代碼(UnitTest\UnitTest\TestScripting_BasicLanguage_CodeGeneration.cpp)里面找到。
posted on 2010-02-26 19:41
陳梓瀚(vczh) 閱讀(2410)
評(píng)論(6) 編輯 收藏 引用 所屬分類:
VL++3.0開發(fā)紀(jì)事