• C语言学习之assert


    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);
        /*插入空指针,程序会报错*/
        return 0;
    }
    

    2)执行的结果

    [zsd@localhost ~]$ gcc  ./assert0case.c -o assert0case
    [zsd@localhost ~]$ ./assert0case
    assert0case: ./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)执行的结果

    [zsd@localhost ~]$ gcc  ./assert0case1.c -o assert0case1
    [zsd@localhost ~]$ ./assert0case1
    assert0case1: ./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. */
    static
    void
    flst_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
    
  • 相关阅读:
    vector详解
    笔记
    积木大赛
    codevs 1086 栈(Catalan数)
    不要把球传我
    同余方程 (codevs1200)
    最小集合
    数的计算
    产生数
    逃跑的拉尔夫
  • 原文地址:https://www.cnblogs.com/zhangshengdong/p/9377040.html
Copyright © 2020-2023  润新知