2009-12-10 26 views

回答

12

通常情況下,您會使用一個斷言來檢查一個條件,如果爲false,則會在您的應用程序中指示一個錯誤。因此,如果在應用程序的某個時間點遇到一個NULL指針,那麼應該不會遇到,除非存在錯誤,否則斷言它。如果由於某些輸入無效而可能會遇到,那麼您需要進行適當的錯誤處理。

+1

如果一個指針永遠不能爲空,那麼你可能想考慮把它變成一個引用(當然,如果可能的話)。 – 2009-12-10 08:45:59

4

您不需要需要根本就在指針上使用斷言。這個想法是確保當它們爲空時解除引用指針時不會崩潰。

你可以用assert做到這一點,但它不是一個非常專業的方式來處理這樣的錯誤,因爲它總是終止程序 - 如果用戶沒有,例如,保存了他們最近三個小時的價值數據輸入。

什麼應該做的指針是檢查它們的無效性和失敗優雅。換句話說,讓你的函數返回某種類型的錯誤或者什麼都不做(不是每個人都會同意這種方法,但是如果它被記錄的話它是完全可以接受的)。

在我看來,assert是爲了捕捉開發過程中遇到的問題,這就是爲什麼你會發現assert在某些編譯器下沒有發佈版本的問題。它是而不是是防守編程的替代品。

至於如何做到這一點:

void doSomethingWithPointer (int *p) { 
    if (p != 0) 
     cout << *p << endl; 
} 

換句話說,即使你的 「合同」(API)指出你」:

#include <assert.h> 
void doSomethingWithPointer (int *p) { 
    assert (p != 0); 
    cout << *p << endl; 
} 

但這會爲得到更好的完成不允許接收空指針,你仍然應該優雅地處理它們。一箇舊的報價:在你給予的內容上保守,在你接受的內容中自由的(換言之)。

+5

另一方面,用戶工作的3小時崩潰和失敗比嘗試「解決」問題和破壞3周的問題更可取。 – 2009-12-10 00:25:19

+0

@Anon,我相信會被「優雅」的一點所覆蓋:-)顯然你必須這樣做*正確*。如果它們在非調試代碼中被禁用,斷言不會幫助您的領域的軟件變得非常小。斷言是用於開發,而不是生產(除非你是那種只將調試代碼發送到現場的類型之一)。 – paxdiablo 2009-12-10 00:43:18

+0

這就是宏在哪裏派上用場:斷言可能在調試模式下產生核心,在釋放模式下產生異常:) – 2009-12-10 14:31:55

4

ASSERT語句與「強制文檔」一樣偉大 - 也就是說,它們會告訴讀者一些關於代碼的內容(「這絕不應該發生」),然後通過讓它知道它們是否不成立來執行它。

如果它的東西,可能發生(無效的輸入,內存無法分配),這使用斷言時間。斷言是只有的事情是不可能發生的,如果每個人都遵守先決條件等。

可正是如此做:

ASSERT(pMyPointer); 
+5

(如果有人想知道,allcaps ASSERT是Microsoft斷言宏,小寫assert是標準的C.) – 2009-12-10 00:36:59

0

我會用一個ASSERT其中一個空指針不會立即導致崩潰,但後來可能導致somethign錯誤這是很難被發現。
如:

ASSERT(p); 
strcpy(p, "hello"); 

是有點多餘,它只是取代了致命的異常有一個致命的斷言!
但是在更復雜的代碼中,特別是像智能指針這樣的東西,知道檢查指針是否屬於你自己的東西可能是有用的。

記住ASSERT只能在調試版本中運行,它們在版本中消失。

2

根據經驗,如果你斷言空條件應該永遠不會發生在正常情況下,你的程序處於非常糟糕的狀態。從這種空狀態恢復將更有可能掩蓋原始問題。

除非你在代碼中考慮異常保證(linky)我說讓它崩潰,那麼你知道你有問題。

+0

我會說:「在任何情況下都不應該發生」。 – 2009-12-10 07:39:47

0

在C,也有在調試模式下斷言功能.. ,如果斷言(X),X的條件是假的,會彈出一個警告... 但請記住它只能在調試模式下... 在釋放模式下,所有斷言函數全部被跳過