assert宏的原型定义在头文件assert.h中,它的作用是如果宏后面的条件返回假,则终止程序的执行,该宏会调用__assert_fail函数,这个函数内部会先向stderr输出错误信息,然后调用abort函数来终止程序的执行。
一,assert宏的定义
如下:
# define assert(expr) \ ((expr) \ ? __ASSERT_VOID_CAST (0) \ : __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION))
__assert_fail函数是一个库导出函数,导出定义如下:
/* 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__));注意上面的__attribute__((__noreturn__))定义,这个属性通知编译器,该函数从不返回。运行完这个函数程序就退出来了。
二,禁用assert宏
这里要注意一个宏,这个宏很有用,可以禁用assert宏,是如何做到的呢?
#ifdef NDEBUG # define assert(expr) (__ASSERT_VOID_CAST (0)) /* void assert_perror (int errnum); If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an error message with the error text for ERRNUM and abort. (This is a GNU extension.) */ # ifdef __USE_GNU # define assert_perror(errnum) (__ASSERT_VOID_CAST (0)) # endif #else /* Not NDEBUG. */所以,就是如果我们自己定义了NDEBUG宏的话,assert就不会工作了,因为__ASSERT_VOID_CAST宏定义如下:
#if defined __cplusplus && __GNUC_PREREQ (2,95) # define __ASSERT_VOID_CAST static_cast<void> #else # define __ASSERT_VOID_CAST (void) #endif
三,assert宏注意事项
#ifndef ASSERT #define ASSERT(x) \ (void)Assert((x), __FUNCTION__, __FILE__, __LINE__, #x) #endifAssert实现如下:
inline bool Assert(bool result, const char* function, const char* file, int line, const char* expression) { if (!result) { Log_Assert(function, file, line, expression); Break(); return false; } return true; }上面的Log_Assert函数只用于输出错误信息。
void Break() { #if WIN32 ::DebugBreak(); #elif OSX // !WIN32 ::Debugger(); #else // !OSX && !WIN32 #if _DEBUG_HAVE_BACKTRACE OutputTrace(); #endif abort(); #endif // !OSX && !WIN32 }DebugBreak是一个VC的库函数,可以对进程附加调试信息,还可以加断点什么的,其实就是我们有时会遇到的问我们是否要调试,如果我们选择是的话,就会启动一个开发环境,打开调试器。