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
posted on 2018-07-27 13:14 东瑜 阅读() 评论() 编辑 收藏
版权声明:本文为zhangshengdong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhangshengdong/p/9377040.html