1. 程式人生 > >空指標、一個錯誤以及static變數

空指標、一個錯誤以及static變數

首先說一下我的編譯環境與我的錯誤:

  • 編譯環境:VS2008,編寫了一個MFC程式,在一個視窗內添加了Tab控制元件,控制元件內有兩個子視窗,一個用於控制另一個用於顯示。

  • 程式Bug:我嘗試著這樣操作:控制視窗->呼叫主視窗的函式(主視窗例項化了兩個子視窗),主視窗的函式會對顯示視窗的控制元件進行操作,進而實現

    控制視窗->主視窗->顯示視窗

    但是出現了這樣的錯誤:

    0xC0000005:Access violation reading location 0x00000200

    作為初學者完全惹不起這個錯誤啊,我苦苦除錯了一天半還是沒有結果,下面是我除錯的歷程,最後結合網上的資料終於發現問題所在。

除錯歷程

  • 努力鎖定問題

    首先我把問題鎖定在我的控制元件上,因為第一次使用TeeChart控制元件,擔心是函式使用不當導致這個問題,後來我只在顯示視窗呼叫TeeChart的函式,發現完全沒有問題,後來我又在主視窗內呼叫TeeChart的函式,發現也沒有問題,注意!!!這些都是一個類內呼叫,沒有在類與類之間傳遞任何引數。(不過在這個過程中我終於搞清楚標頭檔案、cpp檔案和類的關係了,也算有些小的收穫吧。)

  • 發現問題

    既然與TeeChart的函式無關,那問題應該出現在我對主視窗函式的呼叫,當然中間有個小插曲,我在網上看到另外一種說法,說在對控制元件操作前你就把控制元件銷燬也會出現這個問題,但是我程式中並沒有銷燬控制元件啊!
    這個是我控制視窗呼叫主視窗函式的程式碼。

 控制視窗cpp:
 theApp.m_MasterWnd->start();  
 //theApp是我例項化的應用物件,m_MasterWnd是我主視窗的指標

 主視窗cpp:
 start()  //這個是我主視窗的函式,函式會對顯示視窗的控制元件進行操作
 {
     CmainWnd *p = this;
     //m_TabControl  這個是我例項化的顯示視窗的物件,對其操作進而顯示
     p->m_TabContro.Draw();
 }

後來我發現我的p指標是一個空指標!!!為什麼會是空指標呢?我明明用this給它賦值讓它指向主視窗!
然後我就看了一下this的用法,如下:

http://blog.csdn.net/codedoctor/article/details/78087911
內容基本上來自這篇文章。
這篇文章說了類成員函式執行的本質,類的成員函式並不是直接跳到函式體去執行,而是在執行之前傳入一個this指標(在我這個程式中this指標的型別為CmainWnd * const,其值為NULL)

    - 根據指標型別找到成員函式
    - 將this放在一個固定暫存器中傳入然後在所有引數壓棧後再進行壓棧
    - 執行成員函式的程式碼,當使用到非靜態成員變數的時候在其前面加上this-> 

所以this指標在成員函式中一直為NULL,除非呼叫成員函式的指標不為空!

theApp.m_MasterWnd->start();

如果theApp.m_MasterWnd這個指標為空那麼this指標就是一個空指標,所以p是空指標跟m_MasterWnd這個指標有關係,那我就看看這個指標的定義,果然在定義的時候我並沒有對其進行賦值。

然後我對其賦值:

CMainWnd dlg;
m_MasterWnd = &dlg;     //讓指標指向開啟的主視窗
dlg.DoModal();

static變數相關

對於類來說:
static變數是屬於類的,而不是僅屬於某個物件,該類的所有物件均可以呼叫它,類也可以呼叫。物件可以呼叫它,但不可獨佔。不能在類中對其定義(如果在類中對static int N定義,通過物件A對這個靜態變數N操作,那麼對於A來說,靜態變數N會與物件B的靜態變數不同,這與靜態變數的定義相矛盾,所以不能在類中對其定義),也不能在建構函式中對其賦值,這樣每個物件的static的值都會不同,這是不符合條件的。

可能會感覺在空指標中說static是邏輯混亂的,但是它們之間還是有一個關聯的,那就是空指標不能訪問非靜態變數,可以通過這個來驗證自己的指標是否為空指標。

總結

空指標危害大,對我來說很難發現這個錯誤,不過最後還是解決了,指標真的很有用,算是入坑啦。。。。