博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
了解断言
阅读量:5989 次
发布时间:2019-06-20

本文共 2359 字,大约阅读时间需要 7 分钟。

一、看一看断言实现:

  在Linux 中的/usr/include/assert.h中,我们可以看看assert宏的定义:

 

#ifdef    NDEBUG 

# define assert(expr)        (__ASSERT_VOID_CAST (0)) 
    ... 
#endif

 

#if defined __cplusplus && __GNUC_PREREQ (2,95)    

# define __ASSERT_VOID_CAST static_cast<void>    // 如果为c++ 
#else 
# define __ASSERT_VOID_CAST (void)               // 如果为c 
#endif

  当定义NDEBUG时,那么 assert(expr)实际为:static_cast<void>(0)(void)(0)

可以看出,不论是c还是c++,assert在NDEBUG时,Do nothing!
  那如果要禁用assert,很简单,在程序中 #define NDEBUGassertDo noting

  接着向下看:(为了简单起见,只讨论c语言)

# define assert(expr)                            \

  ((expr)                                \
   ? __ASSERT_VOID_CAST (0)                        \
   : __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION))

  当expr为真时,它执行__ASSERT_VOID_CAST(0),也是相当于什么也不做嘛!

  如果expr为假,则执行: __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION))
我们层层展开来:
 /* This prints an "Assertion failed" message and aborts.  */
extern void __assert_fail (__const char *__assertion, __const char *__file,
               unsigned int __line, __const char *__function)
     __THROW __attribute__ ((__noreturn__));

其中:__STRING()会把expr转换成字符串;__FILE__为.c或.cpp文件文件名称;__LINE__为代码所在的行数;__ASSERT_FUNCTION为一个特殊的变量,简单的说它含有定义它的函数名称(具体解释在头文件注释中有详细说明)。

你也可以写一个简单程序看一下这几个变量:

 

运行结果如下:

 

  这几个特殊的变量传给__assert_fail函数,此函数为一个库导出函数,注释中描述这个函数作用是向错误输出中打印"Assertion failed"信息,然后调用abort函数来终止程序执行。

assert宏的原型定义在头文件assert.h中,它的作用是如果宏后面的条件返回假,则终止程序的执行,该宏会调用__assert_fail函数,这个函数内部会先向stderr输出错误信息,然后调用abort函数来终止程序的执行。其中__attribute__((__noreturn__))属性通知编译器,该函数从不返回。

二,assert宏注意事项

  1.最好使用assert宏检查一个条件,就是不要用&&或者||操作符,这样更容易发现是哪个条件出现问题,在需要的时候,多写几个assert宏。

  2.不要使用assert进行变量修改,如assert(k++>10),因为我们可能会禁用这个宏,此时,k++是不会执行的,正如上面我们看到的一样。
  3.assert不是条件过滤。

三,自定义实现ASSERT宏

  我们自己可以定义实现ASSERT宏,这样可以得到更多的错误信息,也可以自己定义错误行为。
#ifndef MYASSERT
#define MYASSERT(x) \
    (void)Assert((x), __FUNCTION__, __FILE__, __LINE__, #x)
#endif
Assert实现如下:
inline bool Assert(bool result, const char* function, const char* file,
                   int line, const char* expression) {
  if (!result) { 
    assertFunc(function, file, line, expression);//你可以打印到错误输出或者写入log

    Break();

    return false;
  }
  return true;
}
Break定义对错误处理的行为,该函数定义如下:
void Break() {
#if WIN32
  ::DebugBreak();
#elif OSX  // !WIN32
  ::Debugger();
#else // !OSX && !WIN32
#if _DEBUG_HAVE_BACKTRACE
  OutputTrace();
#endif
  abort();
#endif // !OSX && !WIN32
}
  DebugBreak是一个VC的库函数,可以对进程附加调试信息,还可以加断点什么的,其实就是我们有时会遇到的问我们是否要调试,如果我们选择是的话,就会启动一个开发环境,打开调试器。
  最好的话,实现MYASSERT时,启用命名空间,这样就更容易控制这个宏了。

转载于:https://www.cnblogs.com/noodlesMoMo/p/3494658.html

你可能感兴趣的文章
劣质代码评析——《写给大家看的C语言书(第2版)》附录B之21点程序(六)...
查看>>
ashx的学习
查看>>
Installing ODIConsole application using weblogic server
查看>>
hp警告Creating default object from empty value 问题的解决方法
查看>>
C#游戏开发中快速的游戏循环
查看>>
如何高效快捷检索得到核心文献?
查看>>
使用MVC写模式jsp连接到数据库操作
查看>>
模拟电路创新设计
查看>>
win10安装blueCFD
查看>>
C# 计算两个字符串的相似度
查看>>
linux 遇见错误Could not get lock /var/lib/dpkg/lock
查看>>
MySQLdump常用命令
查看>>
如何才能正确的关闭Socket连接
查看>>
MongoDB基本操作
查看>>
[转]微擎(微赞)学习之 -- 模块开发:目录结构
查看>>
css 手机适配
查看>>
5个界面效果很炫的JavaScript UI框架
查看>>
根据标准word模板生成word文档类库(开源)
查看>>
Html网页表格结构化标记的应用
查看>>
数据结构和算法 (二)数据结构基础、线性表、栈和队列、数组和字符串
查看>>