C++ Assert()断言机制原理以及使用

合集下载

关于assert断言的使用介绍

关于assert断言的使用介绍

关于assert断言的使用介绍/sentimental_man/blog/static/73001618200871531835407/创作者:Qdieyou,转载请加注。

程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。

(这个概念可能不大好理解,想想VC下,调试时有个选项,一个是debug,一个是release)assert(表达式); 的意思是:当表达式为真时,程序继续运行,如果表达市为假,那程序就会停止运行,并提示错误信息。

注意:assert是一个宏,只在debug版本中起作用,在release版本中,该语句是不起任何作用的。

先简单的看一个例子吧!以下为一个使用了断言的C源程序:#include <stdio.h>#include <assert.h>void test(int *p){assert(p != NULL);printf("%d\n", *p);}int main(void){test(NULL);}编译及运行结果:Qdieyou@qdieyou /cygdrive/e/gcc$ gcc -o assert assert.cQdieyou@qdieyou /cygdrive/e/gcc$ ./assertassertion "p != NULL" failed: file "assert.c", line 619331 [sig] assert 3288 e:\gcc\assert.exe: *** fatal error - called with threadlist_ix -1Hangup程序说明:由于我们在main函数中传了NULL指针值给test函数,在test函数执行到assert(p != NULL);发现表达式不为真,就终止了程序的运行,并提示错误的行数信息。

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的用途说的很清楚:利用编译程序自动查错固然好,但我敢说只要你观察一下项目中那些比较明显的错误,就会发现编译程序所查出的只是其中的一小部分。

我还敢说,如果排除掉了程序中的所有错误那么在大部分时间内程序都会正确工作。

断言assert函数,C语言assert函数完全攻略

断言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 指针,那么问题就严重了。

assert断言

assert断言
4)一般教科书都鼓励程序员们进行防错性的程序设计,但要记住这种编程风格会隐瞒错误。当进行防错性编程时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。
C++ ASSERT() 断言机制 (转载)
只有在生成DEBUG码时ASSERT()才起作用.
在生成Release码时编译器会跳过ASSERT().
不好: assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
好: assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
#include <stdio.h>
#define NDEBUG
#include <assert.h>用法总结与注意事项:
1)在函数开始处检验传入参数的合法性
如:
int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
不是用来检查错误的
当程序员刚开始使用断言时,有时会错误地利用断言去检查真正地错误,而不去检查非法的情况。看看在下面的函数strdup中的两个断言:
char* strdup(char* str)
{
char* strNew;
assert(str != NULL);
strNew = (char*)malloc(strlen(str)+1);

C++断言——精选推荐

C++断言——精选推荐

C++断⾔1、运⾏时断⾔1.1、assert属于运⾏时断⾔,可以在运⾏时判断给定条件是否为真,如果为真则什么也不做,否则打印⼀跳错误信息,然后通过abort来终⽌程。

当程序开发阶段,我们可以在debug模式下加⼊⼤量的运⾏时断⾔,来提⾼我们程序的健壮性,并且提⾼开发速度。

但是当程序需要发布的时候,⼤量的断⾔会影响程序的运⾏效率,此时我们只需要在assert.h头⽂件前加#define NDEBUG.1.2、断⾔有⼀个问题,就是⼀定会abort,强制整个程序退出⽽导致调试也⽆法继续进⾏,就像上图这样,出现问题后,我们知道了出现问题的⾏号,但是我们需要⼿动在该⾏的上⾯设置断点,重新开始调试才能够检查到发⽣问题时各个变量的状态。

⽽且,有时问题不是那么容易重现,于是就可能出现没法重现错误再检查状态的问题。

所以,我们可以⾃⼰写⼀个类似的宏来解决这个问题,我们希望在违反断⾔时触发断点陷阱门中断⽽不是调⽤abort,这样,在违反断⾔时程序会暂停下来,等待程序员来检查当前的状态有何异常#define _ASSERT(x) if (!(x)) __asm {int 3}; //是检查断⾔,然后如果断⾔结果为false(0),那么就调⽤内联汇编指令int 3陷⼊调试中断1.3、⽤户⾃定义断⾔实现功能:断⾔的时候可以⽀持变量输出SMART_ASSERTvalue && "Invalid value!")("1")(s);//头⽂件////////////////////////////////////////////////////////////////////////////////#include#include#include#includeclass Assert{public://编译期,SMART_ASSERT宏被替换,断⾔被命中时//1、如果断⾔后跟有括号括起来的参数时//SMART_ASSERT_C和SMART_ASSERT_N将不会被认为是成员,⽽是SMART_ASSERT_C(x)和SMART_ASSERT_N(x)宏//间接替换为调⽤ShowMemoryValue成员⽅法。

c语言assert函数

c语言assert函数

c语言assert函数c语言assert函数是一种实用的调试工具,它在编程过程中可以帮助开发者迅速发现程序中存在的问题。

assert函数一般用来检查表达式是否成立,如果不成立,则抛出一个自定义的断言错误信息。

本文将详细介绍c语言assert函数的原理、用法,以及assert函数的优缺点。

assert函数的原理与用法assert函数的原理很简单,它就是一段内联的C语言函数,这段函数定义了一个叫做assert的宏,它的工作原理是将它的第一个参数(表达式)计算为0或非0,如果为0,就执行第二个参数(断言错误信息)。

assert函数的格式是:assert(expression, message),其中expression表达式是一个用户自定义的表达式,message是用户可以自定义的断言错误信息。

assert函数的使用方式有多种:(1)通过#include<assert.h>引入assert.h头文件,然后使用assert()函数。

(2)使用宏定义(#define),定义一个assert宏函数,调用assert函数,之后直接使用该宏函数进行调用。

assert函数的优点assert函数是一种常见的调试技术,它可以在编程过程中发现程序中存在的问题,从而帮助开发者及时发现程序的 bug,提高程序的质量。

另外,assert函数的实现简单,只需要简单的函数宏定义,不用太多额外的时间和空间,可以大大简化编程过程。

assert函数的缺点但是assert函数也有一些缺点,例如,它只能检测一些简单的表达式,无法检测复杂的异常情况。

另外,assert函数不能保证程序正确运行,只能提示程序可能存在的问题,最终还是要依靠开发者去检查和修正程序代码。

总结总之,c语言的assert函数是一种简单而有效的实用调试工具,函数的格式简单,实现容易,可以帮助开发者及时发现程序中存在的问题,进而提高程序的质量。

但是assert函数仍然存在一些缺点。

c语言中assert的用法

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会打印一个默认的错误消息。

assert在c语言中的作用

assert在c语言中的作用

assert在c语言中的作用assert在C语言中的作用assert是C语言中的一个宏定义,用于在程序中进行断言。

它的作用是在程序运行时检查一个条件是否为真,如果条件为假,则会输出错误信息并终止程序的运行。

assert的作用类似于程序员在代码中手动添加的断点,可以帮助程序员在开发过程中及时发现程序中的错误。

assert的语法格式如下:```assert(expression);```其中,expression是一个需要检查的条件,如果该条件为假,则assert会输出错误信息并终止程序的运行。

assert的输出信息包括文件名、行号和错误信息,这些信息可以帮助程序员快速定位错误的位置。

assert的使用方法非常简单,只需要在程序中添加需要检查的条件即可。

例如,下面的代码中使用了assert来检查一个数组是否越界: ```#include <stdio.h>#include <assert.h>int main(){int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int index = 11;assert(index >= 0 && index < 10);printf("%d\n", arr[index]);return 0;}```在上面的代码中,我们定义了一个包含10个元素的数组arr,并将index赋值为11。

由于数组的下标从0开始,所以当index等于11时,就会越界。

为了避免这种情况的发生,我们使用了assert来检查index是否越界。

如果index越界,则assert会输出错误信息并终止程序的运行。

assert的作用不仅仅是在程序开发过程中帮助程序员发现错误,它还可以在程序发布后帮助用户发现错误。

当用户在使用程序时遇到错误时,assert输出的错误信息可以帮助用户快速定位问题,并向开发人员反馈错误信息,从而加快问题的解决速度。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MSDN原文如是说:
Evaluates an expression and, when the result is false, prints a diagnostic message and aborts the program.
(判断一个表达式,如果结果为假,输出诊断消息并中止程序。

)[cpp]view plaincopy
print?
1.void assert(
2.int expression
3.);
参数:Expression (including pointers) that evaluates to nonzero or 0.(表达式【包括指针】是非零或零)
原理:assert的作用是现计算表达式expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort 来终止程序运行。

MSDN示例程序;
[cpp]view plaincopy
print?
1.// crt_assert.c
2.// compile with: /c
3.#include <stdio.h>
4.#include <assert.h>
5.#include <string.h>
6.
7.void analyze_string( char *string ); // Prototype
8.
9.int main( void )
10.{
11.char test1[] = "abc", *test2 = NULL, test3[] = "";
12.
13. printf ( "Analyzing string '%s'\n", test1 ); fflush( stdout );
14. analyze_string( test1 );
15. printf ( "Analyzing string '%s'\n", test2 ); fflush( stdout );
16. analyze_string( test2 );
17. printf ( "Analyzing string '%s'\n", test3 ); fflush( stdout );
18. analyze_string( test3 );
19.}
20.
21.// Tests a string to see if it is NULL,
22.// empty, or longer than 0 characters.
23.void analyze_string( char * string )
24.{
25. assert( string != NULL ); // Cannot be NULL
26. assert( *string != '\0' ); // Cannot be empty
27. assert( strlen( string ) > 2 ); // Length must exceed 2
28.}
输出结果
[cpp]view plaincopy
print?
1.Analyzing string 'abc'
2.Analyzing string '(null)'
3.Assertion failed: string != NULL, file assert.cpp, line 25
4.
5.abnormal program termination
用法总结:
1)在函数开始处检验传入参数的合法性
如:
intresetBufferSize(intnNewSize)
{
//功能:改变缓冲区大小,
//参数: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不能代替条件过滤
ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略掉。

(在C中,ASSERT是宏而不是函数),使用ASSERT“断言”容易在debug时输出程序错误所在。

而assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。

使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。

在调试结束后,可以通过在包含#include <assert.h>的语句之前插入#define NDEBUG 来禁用assert调用,示例代码如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>
加入#define NDEBUG之后,上文第一个例子输出结果为:
[cpp]view plaincopy
print?
1.Analyzing string 'abc'
2.Analyzing string '(null)'
3.Analyzing string ''
在面试中经常用到的一个题目:
已知memcpy的函数为:void* memcpy(void *dest , const void* src , size_t count)其中dest是目的指针,src是源指针。

不调用c++/c的memcpy库函数,请编写memcpy。

[cpp]view plaincopy
print?
1.void* memcpy(void *dst, const void *src, size_t count)
2.{
3. //安全检查
4. assert( (dst != NULL) && (src != NULL) );
5.
6. unsigned char *pdst = (unsigned char *)dst;
7. const unsigned char *psrc = (const unsigned char *)src; 8.
9. //防止内存重复
10. assert(!(psrc<=pdst && pdst<psrc+count));
11. assert(!(pdst<=psrc && psrc<pdst+count));
12.
13. while(count--)
14. {
15. *pdst = *psrc;
16. pdst++;
17. psrc++;
18. }
19. return dst;
20.}。

相关文档
最新文档