作者:@张扶摇
本文为作者原创,转载请注明出处:https://www.cnblogs.com/zhangshengdong/p/9377040.html
目录
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
感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统