C++Assert
C语言断言assert的用法

assert的用法assert(<expression>);当expression结果为“假”时,会在stderr中输出这条语句所在的文件名和行号,以及这条表达式。
这只在调试版本中起作用,在Release版本中不会产生任何代码。
通常当我们使用assert时,都在强烈说明一个含义:在这里必然如此。
它通常用于一个函数的先验条件和后验条件的检查。
比如我写一个C风格复制字符串的函数,并且认为调用者不应该传入NULL指针:char * clone_string(const char * source){char * result;assert(source != NULL);result = (char *)malloc(strlen(source) + 1);if (result != NULL){strcpy(result, source);assert(strcmp(result, source) == 0);}return result;}注意到我对source是否为NULL是用assert检查的,但对result是不是为NULL是用if语句判断的,这是因为在调用代码正确的情况下source必然不为NULL,如果断言失败,说明调用代码中有错误,需要修改;但result作为malloc的返回值则不一定,在malloc代码无误的情况下仍然可能返回NULL——当内存块不足时。
最后又用assert对strcpy的结果进行检查,因为只要代码正确,无论什么情况strcpy应该正常完成复制,它没有malloc那种异常情况存在。
在《编程精粹》第二章(自己设计并使用断言)开始的一段话把assert的用途说的很清楚:利用编译程序自动查错固然好,但我敢说只要你观察一下项目中那些比较明显的错误,就会发现编译程序所查出的只是其中的一小部分。
我还敢说,如果排除掉了程序中的所有错误那么在大部分时间内程序都会正确工作。
C语言头文件大全

标准C语言头文件ISO C标准定义的头文件(24项)<assert。
h> 验证程序断言〈complex。
h〉支持复数算术运算〈ctype。
h〉字符类型<errno。
h〉出错码<fenv。
h> 浮点环境〈float。
h> 浮点常量<inttypes。
h> 整型格式转换〈iso646.h〉替代关系操作符宏〈limits。
h> 实现常量<locale.h〉局部类别<math。
h〉数学常量〈setjmp.h> 非局部goto〈signal。
h> 信号〈stdarg。
h〉可变参数表〈stdbool.h> 布尔类型和值〈stddef。
h> 标准定义〈stdint.h〉整型<stdio。
h〉标准I/O库〈stdlib.h〉实用程序库函数〈string。
h〉字符串操作<tgmath.h〉通用类型数学宏<time.h> 时间和日期〈wchar。
h〉宽字符支持〈wctype.h〉宽字符分类和映射支持POSIX标准定义的必须的头文件(26项)〈dirent.h〉目录项<fcntl.h> 文件控制〈fnmatch。
h> 文件名匹配类型〈glob。
h> 路径名模式匹配类型〈grp。
h> 组文件〈netdb.h> 网络数据库操作〈pwd.h〉口令文件<regex。
h> 正则表达式〈tar。
h> tar归档值<termios。
h> 终端I/O <unistd.h> 符号常量<utime.h〉文件时间<wordexp。
h〉字扩展类型<arpa/inet.h> Internet定义<net/if.h> 套接字本地接口〈netinet/in.h> Internet地址族 <netinet/tcp.h〉传输控制协议〈sys/mman。
断言assert函数,C语言assert函数完全攻略

断言assert函数,C语言assert函数完全攻略对于断言,相信大家都不陌生,大多数编程语言也都有断言这一特性。
简单地讲,断言就是对某种假设条件进行检查。
在C 语言中,断言被定义为宏的形式(assert(expression)),而不是函数,其原型定义在<assert.h>文件中。
其中,assert 将通过检查表达式expression 的值来决定是否需要终止执行程序。
也就是说,如果表达式expression 的值为假(即为0),那么它将首先向标准错误流stderr 打印一条出错信息,然后再通过调用abort 函数终止程序运行;否则,assert 无任何作用。
默认情况下,assert 宏只有在Debug 版本(内部调试版本)中才能够起作用,而在Release 版本(发行版本)中将被忽略。
当然,也可以通过定义宏或设置编译器参数等形式来在任何时候启用或者禁用断言检查(不建议这么做)。
同样,在程序投入运行后,最终用户在遇到问题时也可以重新起用断言。
这样可以快速发现并定位软件问题,同时对系统错误进行自动报警。
对于在系统中隐藏很深,用其他手段极难发现的问题也可以通过断言进行定位,从而缩短软件问题定位时间,提高系统的可测性。
尽量利用断言来提高代码的可测试性在讨论如何使用断言之前,先来看下面一段示例代码:1.void*Memcpy(void*dest,const void*src, size_t len)2.{3.char*tmp_dest =(char*)dest;4.char*tmp_src =(char*)src;5.while(len --)6.*tmp_dest ++=*tmp_src ++;7.return dest;8.}对于上面的Memcpy 函数,毋庸置疑,它能够通过编译程序的检查成功编译。
从表面上看,该函数并不存在其他任何问题,并且代码也非常干净。
但遗憾的是,在调用该函数时,如果不小心为dest 与src 参数错误地传入了NULL 指针,那么问题就严重了。
C库头文件的C++名字总是以字母C开头

0.编译C++程序时,编译器自动定义了一个预处理名字__cplusplus,而编译标准C时,自动定义名字__STDC__。
另外几个比较有用的预定义名字是__LINE__(文件的当前编译行数),__FILE__(当前被编译的文件名字),__DATE__(编译日期)和__TIME__(编译时间)。
1.C库头文件的C++名字总是以字母C开头,后面去掉后缀.h的C名字,如<assert.h>在C++库中的名字是<cassert>。
两种使用方法:#i nclude<assert.h>或者#i nclude<cassert>using namespace std;2.静态与动态内存分配的两个主要区别:(1)静态对象是有名字的变量,可以直接进行操作,动态对象是没有名字的变量,可以通过指针间接进行操作;(2)静态对象的分配和释放由编译器自动处理,而动态对象必须由程序员显式的管理,通过new和delete两个表达式来完成。
3.类的缺省构造函数是不需要用户提供任何参数的构造函数。
4.STL中标准数组-vector(文件<vector>),两种遍历方式:(1)通过下标操作符;(2)使用迭代器,如vector<int>::iterator iter;可以通过对iterator解引用来直接访问实际的元素*iter;STL提供了作用于容器类型的泛型算法,头文件<algorithm>。
5.文字常量是不可寻址的。
6.常用的几个转义序列:newline(换行符) \n \14horizontal tab(水平制表符) \tvertical tab(垂直制表符) \vbackspace(退格符) \bcarriage return(回车键) \rformfeed(进纸键) \falert (bell)(响铃符) \a \77.变量和文字常量都有存储区,区别在于变量是可寻址的,对于每个变量,都有两个值与之关联:数据值,称为对象的右值,是被读取的值,文字常量和变量都可以用作右值;地址值,被称为变量的左值,是位置值,文字变量不用被用作左值。
c语言停止运行程序的语句

c语言停止运行程序的语句C语言停止运行程序的语句是指在程序执行过程中,通过特定的语句将程序终止。
下面列举了10个常用的停止运行程序的语句。
1. return语句:return语句用于从函数中返回值,并结束函数的执行。
当在主函数中使用return语句时,可以终止整个程序的执行。
2. exit函数:exit函数用于终止程序的执行,并返回一个状态码给操作系统。
它需要包含在stdlib.h头文件中。
3. _Exit函数:_Exit函数是exit函数的一个变种,它直接终止程序的执行,不会执行任何终止处理程序。
它需要包含在stdlib.h头文件中。
4. abort函数:abort函数用于非正常终止程序的执行。
它会引发一个SIGABRT信号,并调用终止处理程序。
它需要包含在stdlib.h 头文件中。
5. break语句:break语句通常用于循环语句或switch语句中,用于跳出循环或switch语句,从而终止程序的执行。
6. continue语句:continue语句用于循环语句中,用于跳过当前循环的剩余部分,继续执行下一轮循环。
7. assert宏:assert宏用于在程序中插入断言,如果断言条件为假,则终止程序的执行。
它需要包含在assert.h头文件中。
8. signal函数:signal函数用于设置信号处理函数,当接收到指定的信号时,会调用相应的信号处理函数。
信号处理函数可以用于终止程序的执行。
9. longjmp函数:longjmp函数用于跳转到指定的位置,并重新开始执行。
它通常与setjmp函数配合使用,在程序的某个地方设置跳转点,并在需要的地方调用longjmp函数进行跳转。
10. pthread_exit函数:pthread_exit函数用于终止一个线程的执行,并返回一个指定的退出状态。
它需要包含在pthread.h头文件中。
以上是C语言中常用的停止运行程序的语句,它们可以根据具体的需求选择合适的语句来终止程序的执行。
C标准库assert.h的实现详解

C标准库assert.h的实现详解本⽂实例讲解了C标准库<assert.h>的实现过程及相关⽤法。
分享给⼤家供⼤家参考。
具体分析如下:⼀、背景知识头⽂件<assert.h>唯⼀的⽬的就是提供assert宏定义,可以在程序中关键的地⽅使⽤这个宏来进⾏断⾔。
如果⼀处断⾔被证明⾮真,希望程序在标准错误流输出⼀条适当的提⽰信息,并使执⾏异常终⽌。
可以这样写代码:#include<assert.h>...assert(0 <= i && i < sizeof(a) / sizeof(a[0]));当然上⾯的代码不是实战中的最好的形式,程序异常终⽌应该改为某种错误的恢复。
宏NDEBUG可以通过在程序的某些地⽅定义宏NDEBUG来改变assert的展开⽅式如果程序某个包含assert的地⽅没有定义NDEBUG,该头⽂件就会将宏assert定义为活动形式,它就可以展开为⼀个表达式,测试断⾔并在断⾔为假的时候输出⼀条错误信息,然后程序终⽌。
反之,如果定义了NDEBUG,头⽂件就会把这个宏定义为不执⾏任何操作的静⽌形式。
⼆、<assert.h>的使⽤从上⾯的代码中可以看到,可以使⽤⼀个简单的谓词来简化assert:if(!ok)abort(); //在头⽂件<stdlib.h>中声明如果觉得断⾔没有存在的必要,就在包含头⽂件之前加上下⾯的代码:#define NDEBUG //取消断⾔#include<assert.h>可以在整个源⽂件中⽤不同的⽅式控制断⾔,当断⾔在频繁执⾏的循环内部发⽣时,性能可能会急剧下降,或在达到提⽰性的部分之前,⼀个更早的断⾔可能会终⽌程序。
要打开断⾔,可以写:#undef NDEBUG#include<assert.h>要关闭断⾔,可以写:#define NDEBUG#include<assert.h>注意:即使宏NDEBUG已经被定义了,我们仍然可以安全地定义它,这是⼀个良性重定义三、<assert.h>的实现从上⾯的分析知该头⽂件的⼤致框架如下:#undef assert //消除已定义的#ifdef NDEBUG#define assert(expr) ((void) 0) //功能失效#else#define assert (expr) ...#endif⼀个简单的编写宏assert的活动形式的⽅式如下:#define assert(expr) if(!(expr)) \fprintf(stderr, "Assertion failed: %s, file %s, line %i\n", \#expr, __FILE__, __LINE__)这种⽅式因为如下⼏种原因不能接受:1、宏不能直接调⽤库的任何输出函数上⾯的定义中包含fprintf、stderr等在stdio.h中定义的函数或宏,程序可能没有包含这个头⽂件2、宏必须能扩展为⼀个void类型的表达式3、宏应该可以扩展为有效并且紧凑的代码这个版本却总是调⽤了⼀个传递了5个参数的函数修改后的assert宏如下:#undef assert#ifdef NDEBUG#define assert(expr) ((void) 0)#elsevoid __bad_assertion (const char *_mess);#define __str(x) # x#define __xstr(x) __str(x)#define assert(expr) ((expr)? (void)0 : \__bad_assertion("Assertion \"" #expr \"\" failed, file " __xstr(__FILE__) \", line " __xstr(__LINE__) "\n"))#endif其中__LINE__ 是内置宏,代表该⾏代码的所在⾏号,由于__LINE__没有扩展成字符串字⾯量,它变成了⼀个⼗进制常量,把它转换成适当的形式需要⼀个额外的处理层。
C语言中几种输出调试信息的方法

C语言中几种输出调试信息的方法C语言中有多种方法可以输出调试信息,下面列举了几种常见的方法:1. 使用printf函数:这是最简单直接的方法,通过在代码中插入printf语句来输出调试信息。
例如:printf("Debug information\n");2. 使用宏定义:通过定义一系列的宏来简化输出调试信息的代码。
例如:#define DEBUG printf("Debug information\n");3. 使用条件编译:通过在代码中插入条件编译语句,只有在特定条件满足时才输出调试信息。
例如:#ifdef DEBUG printf("Debug information\n"); #endif4. 使用log文件:将调试信息输出到一个log文件中,便于查看、分析。
可以使用标准库函数fopen和fprintf来实现。
例如:FILE *fp = fopen("debug.log", "a"); fprintf(fp, "Debug information\n"); fclose(fp);5. 使用系统日志:调用系统提供的日志函数,将调试信息输出到系统日志中,方便系统管理和追踪调试信息。
例如:syslog(LOG_DEBUG, "Debug information");6.使用调试器:使用调试器对程序进行断点调试,可以逐行查看代码执行过程、变量的值等。
常用的调试器有GDB、LLDB等。
7. 使用assert断言:通过使用assert宏来检查程序中的逻辑错误,并在条件判断失败时输出相应的错误信息。
例如:assert(x > 0);8. 使用日志库:使用第三方的日志库,如Log4c、Glog等,这些库提供了更为丰富的日志输出功能,可以控制日志输出的级别、格式等。
c语言中assert的用法

c语言中assert的用法一、什么是assert在C语言中,assert被称为断言(Assertion)。
它是一种用于检查程序运行时条件是否满足的方法。
当检测到条件不满足时,assert能够打印有关问题的信息,并且使程序停止执行,以便开发人员能够及时发现和修复错误。
二、使用assert进行断言在C语言中,我们可以使用<assert.h>头文件中提供的宏定义来使用assert功能。
1. assert原型assert宏定义的原型如下:```cvoid assert(int expression);```2. assert函数工作原理当表达式expression为false(即非零)时,assert会产生一个错误消息,并终止程序的执行。
如果表达式expression为true(即零),则不会发生任何操作,程序继续正常执行。
3. 使用示例下面这个例子演示了如何在代码中使用assert:```c#include <stdio.h>#include <assert.h>int divide(int a, int b) {assert(b != 0);return a / b;}int main() {int result = divide(10, 0);printf("The result is: %d\n", result);return 0;}```在上述代码中,divide函数用于实现两个数相除。
在函数内部,我们首先使用了一个断言来确保除数b不为零。
如果b为零,assert宏会触发一个错误,并输出相关的错误消息。
这样可以帮助我们在程序运行之前在开发阶段及时发现问题。
需要注意的是,当程序以调试模式编译时(通常使用-g选项),assert会进行断言检查;而当以发布模式编译时,assert语句将被忽略。
4. 自定义错误信息默认情况下,assert会打印一个默认的错误消息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义如下:
#include <assert.h>
void assert( int expression );
assert的作用是现计算表达式expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort 来终止程序运行。
请看下面的程序清单badptr.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;
}
在命令行下运行该程序,结果如下:
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp'' failed.
已放弃
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include <assert.h>的语句之前插入#define NDEBUG 来禁用assert调用,示例代码如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>
assert的用法总结与注意事项:
1、在函数开始处检验传入参数的合法性,如:
int resetBufferSize(int nNewSize)
{ //函数功能:改变缓冲区大小,//函数参数:nNewSize 缓冲区新长度//函数返回值:缓冲区当前长度//说明:保持原信息内容不变//nNewSize<=0表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
}
2、每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观地判断是哪个条件失败,比较下面两种形式的代码:
不好:assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
好:assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
3、不能使用改变环境的语句,因为assert只在DEBUG时生效,这么做的话会使程序在真正运行时遇到问题
错误,例如:assert(i++ < 100);
如果在执行之前i=100,那么这条语句就不会执行,i++这条命令就没有执行。
正确的写法:assert(i < 100) i++;
4、assert和后面的语句应空一行,以形成逻辑和视觉上的一致感。
5注意,有的地方,assert不能代替条件过滤。
以下内容摘自《高质量C/C++编程指南》Page 41-42...
程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。
assert 是仅在Debug 版本起作用的宏,它用于检查“不应该”发生的情况
assert 不是函数,而是宏。
程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。
如果程序在assert 处终止了,并不是说含有该assert 的函数有错误,而是调用者出了差错,assert 可以帮助我们找到发生错误的原因。
assert宏中应该包含的元素:判断条件;输出当前断言失败的位置(文件、行数等);返回错误;终止程序...
几种典型的assert的写法:
VC中的写法:
#define ASSERT(f) \
do \
{ \
if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__)) \ AfxDebugBreak(); \
} while (0) \
#define _ASSERT(expr) \
do { if (!(expr) && \ (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, NULL, NULL))) \ _CrtDbgBreak(); } while (0)
其他平台的写法:
# define ASSERT(x) ((x) || (dbg_printf("assertion failed ("__FILE__":%d): \"%s\"\n",__LINE__,#x), break_point(), FALSE))。