assert()用法

 

/* assert example */

#include <stdio.h>

#include <assert.h>

 

void print_number(int* myInt) {

  assert (myInt!=NULL);

  printf ("%d/n",*myInt);

}

 

int main ()

{

  int a=10;

  int * b = NULL;

  int * c = NULL;

 

  b=&a;

 

  print_number (b);

  print_number (c);

 

  return 0;

}

 

 

In this example, assert is used to abort the program execution if print_number is called with a null pointer as attribute. This happens on the second call to the function, which triggers an assertion failure to signal the bug

 

 

 

在這個定義裏,當定義了預處理符號NDEBUG的時候,斷言是無效的,這意味着assert斷言宏只在你的Debug版本中有效。在Release版本里,assert斷言宏不進行任何計算。由於這個而會引起一些側面效裏

 

 

斷言使用方式

斷言可以有兩種形式   1.assert Expression1   2.assert Expression1:Expression2   其中Expression1應該總是一個布爾值,Expression2是斷言失敗時輸出的失敗消息的字符串。如果Expression1爲假,則拋出一個 AssertionError,這是一個錯誤,而不是一個異常,也就是說是一個不可控制異常(unchecked Exception),AssertionError由於是錯誤,所以可以不捕獲,但不推薦這樣做,因爲那樣會使你的系統進入不穩定狀態。

編輯本段啓用斷言

斷言在默認情況下是關閉的,要在編譯時啓用斷言,需要使用source1.4標記 既javac source1.4 Test.java ,在運行時啓用斷言需要使用 -ea參數 。要在系統類中啓用和禁用斷言可以使用 -esa 和 -dsa參數。   例如:   public class AssertExampleOne{   public AssertExampleOne(){}   public static void main(String args[]){   int x=10;   System.out.println("Testing Assertion that x==100");   assert x=100:"Out assertion failed!";   System.out.println("Test passed!");   }   }   如果編譯時未加 -source1.4,則編譯通不過   在執行時未加 -ea 時輸出爲   Testing Assertion that x==100   Test passed   jre忽略了斷言的就代碼,而使用了該參數就會輸出爲   Testing Assertion that x==100   Exception in thread "main" java.lang.AssertionError: Out assertion failed!   at AssertExampleOne.main(AssertExampleOne.java:6)   斷言的副作用   由於程序員的問題,斷言的使用可能會帶來副作用 ,例如:   boolean isEnable=false;   //...   assert isEnable=true;   這個斷言的副作用是因爲它修改了程序中變量的值並且未拋出錯誤,這樣的錯誤如果不細心的檢查是很難發現的。但是同時我們可以根據以上的副作用得到一個有用的特性,根據它來測試斷言是否打開。   public class AssertExampleTwo{   public static void main(String args[]){   boolean isEnable=false;   //...   assert isEnable=true;   if(isEnable==false){   throw new RuntimeException("Assertion shoule be enable!");   }   }   }

編輯本段何時需要使用斷言

1.可以在預計正常情況下程序不會到達的地方放置斷言 :assert false   2.斷言可以用於檢查傳遞給私有方法的參數。(對於公有方法,因爲是提供給外部的接口,所以必須在方法中有相應的參數檢驗才能保證代碼的健壯性)   3.使用斷言測試方法執行的前置條件和後置條件   4.使用斷言檢查類的不變狀態,確保任何情況下,某個變量的狀態必須滿足。(如age屬性應大於0小於某個合適值)

編輯本段什麼地方不要使用斷言

斷言語句不是永遠會執行,可以屏蔽也可以啓用   因此:   1.不要使用斷言作爲公共方法的參數檢查,公共方法的參數永遠都要執行   2.斷言語句不可以有任何邊界效應,不要使用斷言語句去修改變量和改變方法的返回值

編輯本段C裏面的宏

宏名: assert   功 能: 測試一個條件並可能使程序終止   用 法: void assert(int test);   程序例:   #include <assert.h>   #include <stdio.h>   #include <stdlib.h>   struct ITEM {   int key;   int value;   };   /* add item to list, make sure list is not null */   void additem(struct ITEM *itemptr) {   assert(itemptr != NULL);   /* add item to list */   }   int main(void)   {   additem(NULL);   return 0;   }   assert() 宏用法   assert宏的原型定義在<assert.h>中,其作用是如果它的條件返回錯誤,則終止程序執行,原型定義:   #include <assert.h>   void assert( int expression );   assert的作用是先計算表達式 expression ,如果其值爲假(即爲0),那麼它先向stderr打印一條出錯信息,   然後通過調用 abort 來終止程序運行。   請看下面的程序清單badptr.c:   #include <stdio.h>   #include <assert.h>   #include <stdlib.h>   int main( void )   {   FILE *fp;   fp = fopen( "test.txt", "w" );//以可寫的方式打開一個文件,如果不存在就創建一個同名文件   assert( fp ); //所以這裏不會出錯   fclose( fp );   fp = fopen( "noexitfile.txt", "r" );//以只讀的方式打開一個文件,如果不存在就打開文件失敗   assert( fp ); //所以這裏出錯   fclose( fp ); //程序永遠都執行不到這裏來   return 0;   }   [root@localhost error_process]# gcc badptr.c   [root@localhost error_process]# ./a.out   a.out: badptr.c:14: main: Assertion `fp' failed.   已放棄   使用assert的缺點是,頻繁的調用會極大的影響程序的性能,增加額外的開銷。   在調試結束後,可以通過在包含#include <assert.h>的語句之前插入 #define NDEBUG 來禁用assert調用,示例代碼如下:   #include <stdio.h>   #define NDEBUG   #include <assert.h>   用法總結與注意事項:   1)在函數開始處檢驗傳入參數的合法性   如:   int resetBufferSize(int nNewSize)   {   //功能:改變緩衝區大小,   //參數:nNewSize 緩衝區新長度   //返回值:緩衝區當前長度   //說明:保持原信息內容不變 nNewSize<=0表示清除緩衝區   assert(nNewSize >= 0);   assert(nNewSize <= MAX_BUFFER_SIZE);   ...   }   2)每個assert只檢驗一個條件,因爲同時檢驗多個條件時,如果斷言失敗,無法直觀的判斷是哪個條件失敗   不好: assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);   好: assert(nOffset >= 0);   assert(nOffset+nSize <= m_nInfomationSize);   3)不能使用改變環境的語句,因爲assert只在DEBUG個生效,如果這麼做,會使用程序在真正運行時遇到問題   錯誤: assert(i++ < 100)   這是因爲如果出錯,比如在執行之前i=100,那麼這條語句就不會執行,那麼i++這條命令就沒有執行。   正確: assert(i < 100)   i++;   4)assert和後面的語句應空一行,以形成邏輯和視覺上的一致感   5)有的地方,assert不能代替條件過濾   注意:當對於浮點數:   #include<assert.h>   // float pi=3.14;   // assert(pi=3.14); //   float pi=3.14f;   assert (pi=3.14f);   ---------------------------------------------------------   在switch語句中總是要有default子句來顯示信息(Assert)。   int number = SomeMethod();   switch(number)   {   case 1:   Trace.WriteLine("Case 1:");   break;   case 2:   Trace.WriteLine("Case 2:");   break;   default :   Debug.Assert(false);   break;   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章