標籤:表示 否則 就是 細節 red 它的 null 指標 開啟 nod
C語言學習之assert
assert (編程術語)
編寫代碼時,我們總是會做出一些假設,斷言就是用於在代碼中捕捉這些假設,可以將斷言看作是異常處理的一種進階形式。斷言表示為一些布林運算式,程式員相信在程式中的某個特定點該運算式值為真。可以在任何時候啟用和禁用斷言驗證,因此可以在測試時啟用斷言,而在部署時禁用斷言。同樣,程式投入運行後,終端使用者在遇到問題時可以重新啟用斷言。
C語言中assert的用法
assert是宏,而不是函數。在C的assert.h標頭檔中。
assert宏的原型定義在<assert.h>中,其作用是如果它的條件返回錯誤,則終止程式執行。
assert的細節是先計算運算式expr,如果其值為假(即為0),那麼它會列印出來assert的內容和__FILE__, LINE, __ASSERT_FUNCTION,然後執行abort()函數使kernel殺掉自己並coredump(是否產生coredump檔案,取決於系統配置);否則,assert()無任何作用。
- 例1的程式清單assert0case.c
1)assert0case.c的程式
#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*/ /*添加項目之列表中,使用了assert*/}int main(void){ additem(NULL); /*插入null 指標,程式會報錯*/ return 0;}
2)執行的結果
[[email protected] ~]$ gcc ./assert0case.c -o assert0case[[email protected] ~]$ ./assert0caseassert0case: ./assert0case.c:12: additem: Assertion `itemptr!=((void *)0)‘ failed./*可以看到代碼12行出現了問題,想插入NULL,但是列表不讓*/Aborted (core dumped)
- 例2的程式清單assert0case1.c
1)assert0case1.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;}
2)執行的結果
[[email protected] ~]$ gcc ./assert0case1.c -o assert0case1[[email protected] ~]$ ./assert0case1assert0case1: ./assert0case1.c:10: main: Assertion `fp‘ failed./*可以看到代碼第10行出現了問題,想開啟noexitfile.txt的檔案,但是沒有,所以C語言報錯*/Aborted (core dumped)
/***************************分割線******************************/
以上實驗的目的,看MySQL核心的源碼。很多地方用到了如下語句。
原始碼的位置在fut/fut0lst.cc.發現多次使用了ut_ad語句。
/********************************************************************//**Adds a node to an empty list. */staticvoidflst_add_to_empty(/*==============*/ flst_base_node_t* base, /*!< in: pointer to base node of empty list */ flst_node_t* node, /*!< in: node to add */ mtr_t* mtr) /*!< in: mini-transaction handle */{ ulint space; fil_addr_t node_addr; ulint len; ut_ad(mtr && base && node); ut_ad(base != node); /*這裡多次用到了ut_ad語句,可以查看include/ut0dbg.h檔案*/ ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX)); len = flst_get_len(base, mtr); ut_a(len == 0); buf_ptr_get_fsp_addr(node, &space, &node_addr); /* Update first and last fields of base node */ flst_write_addr(base + FLST_FIRST, node_addr, mtr); flst_write_addr(base + FLST_LAST, node_addr, mtr); /* Set prev and next fields of node to add */ flst_write_addr(node + FLST_PREV, fil_addr_null, mtr); flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr); /* Update len of base node */ mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);}
在分析include/ut0dbg.h檔案,發現ut_ad語句的聲明如下:
#ifdef UNIV_INNOCHECKSUM#define ut_a assert /*全部都是assert斷言*/#define ut_ad assert#define ut_error assert(0)#else /* !UNIV_INNOCHECKSUM */#ifdef UNIV_DEBUG/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */#define ut_ad(EXPR) ut_a(EXPR)/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */#define ut_d(EXPR) do {EXPR;} while (0)#else/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */#define ut_ad(EXPR)/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */#define ut_d(EXPR)#endif
C語言學習之assert