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
原文地址:https://www.cnblogs.com/zhangshengdong/p/9377040.html