最近使用了專案公共庫中看起來很穩定的乙個訊息佇列類(前同事留下的),起初用得還挺好。後來程式中突然出現了記憶體暴漲的情況,最後定位下來是這個類的問題。隨後花了一些時間定位出現問題的**,其實在debug時都沒有找到問題**,真正找到問題是憑著感覺在一堆**裡揪出了這樣一句話:
delete (void*)lparam;
靈感突現,這句應該有問題。當時在辦公室,不能上網且手裡又沒有現成的參考資料,於是隨手寫了個簡單的demo測試這句話。
class ca
; ~ca()
;private:
char *m_tmp;
};int _tmain(int argc, _tchar* argv)
return
0;}
果然記憶體蹭蹭蹭就漲上去了。看了的確不能這樣用。那麼問題又來了,delete p1;與delete ca 又有何區別呢?
懷著一顆好奇心,我用vs編譯後下斷點,直接檢視反彙編。
delete ca;//
0028106f test esi,esi
00281071 je wmain+85h (281085h)
00281073
mov eax,dword ptr [esi]
00281075
push eax
00281076
call edi
00281078
push offset string "\xcf\xfa\xbb\xd9ca" (2820fch)
0028107d call ebx
0028107f push esi
00281080
call edi
00281082
add esp,0ch
delete p1;
00281085
push esi
00281086
call edi
00281088
add esp,4
delete (ca*)p1;
0028108b test esi,esi
0028108d je wmain+0a1h (2810a1h)
0028108f mov ecx,dword ptr [esi]
00281091
push ecx
00281092
call edi
00281094
push offset string "\xcf\xfa\xbb\xd9ca" (2820fch)
00281099
call ebx
0028109b push esi
0028109c call edi
0028109e add esp,0ch
彙編用得很少,不過基本的東西看懂應該沒問題。由於是使用win32release版本,所以沒有那麼多干擾項,edi的值就是delete操作的位址,esi的值是ca指標的位址。能夠直接看到delete p1時,只將ca位址入棧,然後call delete操作。而delete ca時,彙編有一大堆,主要功能是將ca類的析構函式展開成彙編。當然這是msvc編譯器做的事情。我就沒有繼續深究下去了。
回到家,順便查了下資料。原來對乙個void*型別的delete,是不會呼叫類本身的析構方法的。這個結論與我得出的相符,只不過我使用反彙編的推論侷限於編譯器。
乙個關於空指標的思考
最近在看 時發現乙個用於求結構體成員偏移量的方式 define nbb offsetof struct,field nbb buf size nbb byte struct 0 field nbb byte 0 奇怪的是對 struct 0 field的引用怎麼不會出現錯誤呢?於是寫了如下 進行簡單...
今天解決了乙個空指標
swagger裡傳入請求資料時,老是報nullpointerexception debug時發現會出現這麼一行 cannot find local variable 原因是資料庫表裡後來加了個擴充套件欄位param1,然而在請求報文裡有命名規範為sid,雖然實體類裡改了資料庫的字段,但是請求報文轉換...
乙個指標釋放後不置空的危害
今天面試碰到這個問題了,可以說這個問題是我回答最冤枉的。我覺得我對這個問題,有很清晰的認識。但是不知道為什麼,嘴禿嘍了一句記憶體洩漏,真想打自己乙個大嘴巴。記憶體洩漏的情況的產生是 例如 用int p int malloc sizeof int 讓p重新指向其它,這樣用malloc 開闢的空間就找不...