C语言中的assert

C语言中的assert

https://blog.csdn.net/dacxu/article/details/27313799

assert(expression);

若expression表达式为false,当前进程会调用abort终止运行,并且会向stderr写一条消息。

这条消息根据不同的实现有所不同,但是至少会包括,assert所在的源文件的文件名,行号,及对对应的expression。

另外,若在release状态下,assert宏会被定义为void(0)。

首先介绍宏_CRT_WIDE(_string)

#define __CRT_WIDE(_String) L##_String  
#define _CRT_WIDE(_String) __CRT_WIDE(_String)  

作用是在字符串String前面加上L,变成宽字符串(一个字符两个字节),因为接下来需要调用的函数的参数为w_char类型,两层宏定义用来保证_String也为宏定义时可以展开,##的用法详见https://blog.csdn.net/xiaoyink/article/details/80211141

assert宏的定义如下:

#ifdef  NDEBUG  
  
    #define assert(_Expression)     ((void)0)  
  
#else  
  
    void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line);  
    #define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )  
  
#endif   

release状态下会定义NDEBUG宏,此时assert什么也不做。在DEBUGU状态下,assert(_Expression)首先被替换成||表达式。根据||表达式的规则首先计算(!!(_Expression))的值,如果为true,||后面的表达式不会做计算。如果为false,将会计算后面的表达式。然而,后面的表达式是一个_wassert函数调用,对应的参数为_Expression对应的字符串,assert所在的文件名,及行号,_CRT_WIDE(#_Expression),#_Expression将_Expression其转化成字符串,然后转化成宽字符串传入_wassert()函数。

mingw的_wassert函数实现如下:

extern int mingw_app_type;  
      
void __cdecl _wassert(const wchar_t *_Message,const wchar_t *_File,unsigned _Line)  
{  
    wchar_t *msgbuf = (wchar_t *) malloc (8192*sizeof(wchar_t));  
  
    if (!_File || _File[0] == 0)  
        _File = L"<unknown>";  
  
    if (!_Message || _Message[0] == 0)  
        _Message = L"?";  
  
    _snwprintf (msgbuf, 8191,  
        L"Assertion failed!\n\nFile: %ws, Line %u\n\nExpression: %ws",  
        _File,_Line, _Message);  
  
    if (mingw_app_type == 0)  
        fwprintf (stderr, L"%ws\n", msgbuf);  
    else  
        OutputDebugStringW(msgbuf);  
  
    abort ();  
}  
显然,上面的实现不难。msbuf中存放的就是要打印的输出。根据不同的app类型,输出方式不一样。如果是普通的命令行方式,输出到stderr。如果是图形应用,估计会跳出一个窗口吧!程序最后会调用一个abort,结束程序。当然,进程都结束了,msbuf会自动释放,没必要手工释放了。

猜你喜欢

转载自blog.csdn.net/xiaoyink/article/details/80198184