經(jīng)常存在這樣一種情況,寫代碼的時候按照一種固有思維去寫,可能時間久了都沒有考慮過為什么這么寫,不這么寫會引起什么錯誤。我時常有這樣的困惑,了解太少,有時候遇到蹊蹺的事情也沒時間探究。
今天在跟蹤mfc庫的時候,遇到一件事情使我非常驚訝,徹底打破了我對空對象指針的看法。在我的概念里面,空的對象指針是不能使用的,不能調(diào)用方法。不知道大家有沒有這樣的想法,事實(shí)證明是不對的。下面看看我跟蹤的代碼:
CWnd
*
?PASCAL?CWnd::FromHandle(HWND?hWnd)
{
????CHandleMap
*
?pMap?
=
?afxMapHWND(TRUE);?
//
create?map?if?not?exist
????ASSERT(pMap?
!=
?NULL);
????CWnd
*
?pWnd?
=
?(CWnd
*
)pMap
->
FromHandle(hWnd);
#ifndef?_AFX_NO_OCC_SUPPORT
????pWnd
->
AttachControlSite(pMap);
#endif
????ASSERT(pWnd?
==
?NULL?
||
?pWnd
->
m_hWnd?
==
?hWnd);
????
return
?pWnd;
}
#include?<iostream>
using?namespace?std;
class?CObj

{
public:
????void?Test();
public:
????static?int?m_iInt;
};
int?CObj::m_iInt?=?100;
void?CObj::Test()

{
????cout?<<?m_iInt?<<?endl;
}
int?main(int?argc,?char*?argv[])

{
????CObj*????????pObj????=?(CObj*)1;
????pObj->Test();
????((CObj*)0)->Test();
????((CObj*)1)->Test();
????CObj????????obj;
????obj.Test();
????return?0;
}下面看看匯編,因?yàn)橹挥型ㄟ^匯編才能了解更深的問題:
25:???????CObj*???????pObj????=?(CObj*)1;
00401848???mov?????????dword?ptr?[ebp-4],1
26:???????pObj->Test();
0040184F???mov?????????ecx,dword?ptr?[ebp-4]
00401852???call????????@ILT+565(CObj::Test)?(0040123a)
27:???????((CObj*)0)->Test();
00401857???xor?????????ecx,ecx
00401859???call????????@ILT+565(CObj::Test)?(0040123a)
28:???????((CObj*)1)->Test();
0040185E???mov?????????ecx,1
00401863???call????????@ILT+565(CObj::Test)?(0040123a)
29:???????CObj????????obj;
30:???????obj.Test();
00401868???lea?????????ecx,[ebp-8]
0040186B???call????????@ILT+565(CObj::Test)?(0040123a)
ecx里面存放的是對象的this指針,@ILT是函數(shù)的入口點(diǎn),調(diào)用時將ecx傳遞到函數(shù)內(nèi)部,其實(shí)對于編譯器函數(shù)是全局的,函數(shù)調(diào)用的時候都需要傳遞this指針作為第一個參數(shù)傳遞過去。所以可以上面的代碼在內(nèi)存訪問方面都是合法的,一旦訪問this的非靜態(tài)成員變量,勢必導(dǎo)致非法內(nèi)存訪問。
順便侃侃編譯器優(yōu)化,我不懂到底那個操作效率高,只談?wù)剠^(qū)別。
((CObj*)0)->Test();和((CObj*)1)->Test();對應(yīng)的匯編:
00401857???xor?????????ecx,ecx
00401859???call????????@ILT+565(CObj::Test)?(0040123a)
和
0040185E???mov?????????ecx,1
00401863???call????????@ILT+565(CObj::Test)?(0040123a)
靠,這都有區(qū)別,0指針的時候異或一下剛好是0。無奈啊,編譯器確實(shí)好智能。


