再談讓C++更像C#:C#內存泄露問題
前段時間寫了一篇日志叫《讓C++更像C#》,但我寫的那段示例代碼中的有關內存泄漏的問題當時我說先不管,其實是那時沒有找到很好的解決方法。不好解決C#內存泄露的原因是,沒有辦法去判斷一個指針到底是指向堆內存,還是指向棧內存(windows系統沒有API來實現這樣的功能)。當時google、baidu都搜遍了,沒有找到解決辦法。
現在,就進一步研究這個C#內存泄露的問題。
今天在看國外的一篇技術文章的時候,發現有人就在研究這個問題!他給出了一種解決辦法。首先把他介紹,操作系統會為每一個系統中運行的線程分配一個數據結構叫做TIB(Thread Information Block)或者叫TEB(Thread Enviroment BLock)。里面記錄了與某個線程相關的所有信息。當然包括線程相關的堆棧地址信息。而堆棧的棧頂與棧基址分別存放在FS寄存器的4與8位置處。所以他通過嵌入式匯編實現了判斷指針是棧指針,還是堆指針的方法。代碼如下:
- bool IsMemoryOnStack( LPVOID pVoid )
- {
- LPVOID dwStackTop = 0;
- LPVOID dwStackLowCurrent = 0;
- __asm
- {
- mov EAX, FS:[4]
- mov dwStackTop, eax
- mov EAX, FS:[8]
- mov dwStackLowCurrent, eax
- }
- if( pVoid < = dwStackTop && pVoid >= dwStackLowCurrent )
- {
- // The memory lie between the stack top and stack commited.
- return true;
- }
- // Pointer dosen't point to the stack
- return false;
- }
現在只需要把CTest可能引起內存泄漏的函數修改為如下,就可以解決問題了:
- CTest(CTest* & t)
- {
- this->x=t->getX();
- if(!IsMemoryOnStack(t))
- {
- delete t;
- t=0;
- }
- }
這里使用指針引用的好處是在防止在釋放了指針的內存后,用戶繼續訪問指針的內存。
到此為止,問題全部解決了!印度的軟件行業確實是挺牛比的!
這樣,這個C#內存泄露問題就解決了。有關TIB的技術參考為:
http://www.microsoft.com/msj/archive/S2CE.aspx
【編輯推薦】