VB中CopyMemory函數的問題?
如題,在使用copymemory函數讀取二進位文件時,先讀取144-147位元組時,結果Num的值總為0,如代碼1,若先讀取148-151,再讀取144-147時,結果就正確,如代碼二。(其中144-147位元組為1,0,0,0),有沒有人知道為什麼兩行代碼換個位置結果就不同?
代碼一:
Dim Num As Integer,NumPoints as Integer
Call CopyMemory(Num, pByte(144), 4)
Call CopyMemory(NumPoints1, pByte(148), 4)
Print Num(結果為0)
代碼二:
Dim Num As Integer,NumPoints as Integer
Call CopyMemory(NumPoints1, pByte(148), 4)
Call CopyMemory(Num, pByte(144), 4)
Print Num(結果為1)
我來回答題主的疑惑吧,其實是棧上數據互相覆蓋導致的。
首先VB6里Integer類型的長度是2位元組,但你CopyMemory複製的是4位元組,所以,後一條CopyMemory會寫越界。
那麼再看越界行為,我個人分析,棧的內存分布是這樣的:
+-------------+ 低地址,棧基地址
| NumPoints | 2 位元組
+-------------+
| Num | 2 位元組
+-------------+ 高地址
在代碼一里,你的第二句CopyMemory會複製4位元組到NumPoints的地址上,但這個變數只有2個位元組,於是就把後面的Num給覆蓋了。我猜測pByte 148~152的內容應該也是00結尾的,所以最終輸出的Num值就是0
反過來的代碼二就沒有問題,但是反過來的話你的第二句CopyMemory會覆蓋到別的東西,具體是什麼就要看你代碼怎麼寫的了。而代碼二里第一句實際上也覆蓋了一次Num的值,不信你可以先給Num一個初始值,再在代碼二CopyMemory(NumPoints1, pByte(148), 4)之後列印一下Num值,肯定是0
如果你學一下C語言這種問題就很容易發現了。
對於VB來說,CopyMemory比較危險,最可靠的做法是用len來確定要複製的內存大小,比如CopyMemory Num, pByte(148), len(Num)
這樣就可靠多了。
-------------------------------------昨天填了這個坑以後覺得好像不太對-------------------------------------
於是反彙編了一下VB生成EXE文件:
再看運行結果:
結果居然不一樣!然後我就挨個編譯選項試了一下,發現除了生成P代碼以外,其餘的生成的本地代碼運行結果都是1,反彙編也證明雖然integer的大小是2位元組,但生成彙編都是以4位元組對齊的。
我猜題主肯定沒試過生成EXE,因為EXE的結果跟VB里是不一樣的。
那麼為什麼P代碼以及VB里運行時結果是不同的,只能通過反彙編P代碼試試了。
P代碼是一種解釋型的語言,大部分實際代碼都跑在VB的DLL里,但通過反彙編還是可以定位到CopyMemory的位置。
通過適當修改代碼,這樣就可以更清楚的定位,可以發現在P代碼模式里,兩個integer確實是挨著的,沒有按4位元組對齊:
1. 題主這種情況肯定是不正確的,但如果生成EXE也可能會有正確的值;
2. VB里和P代碼模式下VB採用解釋運行的方法,與直接生成本地代碼結果不同;3. 不同模型下棧上數據的對齊方式不同。-完-問題已解決,原來是數據類型定義的問題,把Integer型改成Long型就好了,但是在定義為Integer時,代碼二的運行結果居然正確,實在令人費解
推薦閱讀:
※學 ASP.NET 的話是 VB.NET 好還是 C# 好?
※VB中ptivate sub中sub什麼意思?
※web前端設計有沒有類似vb,vc這類的可視化編程工具,用戶添加圖形,軟體工具自動生成代碼?
TAG:VisualBasic |