2012-08-02 50 views
0

我有一個複雜的A類:有什麼方法可以避免在C++中使用非法指針?

class A{ 
... 
}; 

和B類是包括A的指針,並且具有返回指針的方法。

class B{ 
A* GetA(){return pA;} 
A* pA; 
}; 

然後,當我用「木屐」,以獲得一個A的指針,它更容易使用非法指針,如:

void func(A* p){ 
B b; 
p = b.GetA(); 
} 
當我使用「功能」

,我只是得到一個非法指針。上面的代碼只是一個示例。我發現當我處於多線程環境時,很容易犯這個錯誤。

有什麼方法可以讓我確定避免這些錯誤嗎?

非常感謝

+3

考慮shared_ptr而不是原始指針? – Jaywalker 2012-08-02 16:41:55

+2

這是觸發未定義行爲的編碼錯誤;它與多線程無關。你的編譯器不會提醒你這種情況嗎? – dasblinkenlight 2012-08-02 16:42:42

+4

考慮在'B'的構造函數中初始化'pA'?如果沒有有效的「pA」,沒有辦法創建'B'的實例。 – Damon 2012-08-02 16:42:53

回答

2

有一個在C++沒有通用的方法來保護自己免受非法指針訪問,但也有你可以用它來保護自己的成語。

將您的類保留爲表示概念/對象,並且不公開直接訪問它們可能包含的指針。優選例如描述性方法,或者用於類似容器的類風格方法begin/end風格方法。

管理指針時,首先要使用標準容器,如vector。他們高度優化和調試,並防止許多問題,因爲他們已經擁有了所有正確的構造函數,賦值,析構函數等

如果一個標準集裝箱是不可能喜歡智能指針如unique_ptrscoped_ptrshared_ptrweak_ptr,這取決於你的指針需求。通過使用適當的智能指針,再次使您幾乎不可能無意識地編碼錯誤。

即使使用所有這些指導原則,您也可以繞過您嘗試實施的任何保護措施。如果你發現自己使用了很多演員,你應該退後一步並重新檢查你的設計。

在你的情況下,我不但不能通過訪問器訪問pA,我也不會讓它成爲一個原始指針。

+0

非常感謝。我會在我的代碼中嘗試你的方法。 – aasa 2012-08-03 00:52:41

0

如果初始化在構造函數中NULL指針:

class B { 
    B() { 
     pA = NULL; 
    } 
    A* GetA(){return pA;} 
    A* pA; 
} 

然後,你可以檢查,看看是否指針使用它之前非NULL。

void func(A* p){ 
    B b; 
    p = b.GetA(); 
    if(p != NULL) { 
     //use p 
    } 
} 

而且,它似乎很奇怪,你傳遞一個指針的函數,則無需先使用其分配給它。 p = b.GetA();不會改變func以外的任何內容。也許你的意思是做一些像這樣的事情?

//Caller passes reference to their pointer, caller's pointer gets set. 
void func(A *&p) { 
    B b; 
    p = b.GetA(); 
} 
//Caller passes pointer to their pointer, caller's pointer gets set. 
void func(A **p){ 
    B b; 
    if(p != NULL) { 
     *p = b.GetA(); 
    } 
} 
+0

我認爲它只在'func'方法中有用,當func返回時,'b'將被破壞,然後返回值p將是一個非法指針,它不會等於'NULL',( 0xcccc meybe),並且將它與'NULL'進行比較是無用的 – aasa 2012-08-03 00:48:35

+0

它取決於如何分配'pA'的有效值。如果你動態分配內存,在'b'超出範圍之後,指針仍然有效。但爲什麼指針的值會改變?除非分配了新值,否則該值不會更改。 – 2012-08-03 01:19:42

+0

讓我們認爲b是一個容器,而pA是來自b的元素。當我選擇pA時,這意味着我有一個複製指針pA'存儲在b中的pA,然後pA'與b沒有關係。當b失蹤時,b中的pA將是空閒的。但是,因爲pA'是pA的副本,所以pA'仍指向由pA釋放的內存。所以,當我再次使用pA'時,這將是一個錯誤。 – aasa 2012-08-03 02:05:08

相關問題