C++ assert宏实现原理

来源:互联网 发布:android书籍推荐 知乎 编辑:程序博客网 时间:2024/06/11 14:00

assert(expression);

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

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

另外,若在release状态下,assert宏会被自动remove掉。

我对assert宏的实现非常感兴趣。显然,如果了解了其实现原理,那么我们可以自己实现类似于assert的宏。


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

assert宏的定义如下:

#ifdef  NDEBUG#define assert(_Expression)     ((void)0)#elsevoid _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所在的文件名,及行号。


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);elseOutputDebugStringW(msgbuf);abort ();}

显然,上面的实现不难。msbuf中存放的就是要打印的输出。根据不同的app类型,输出方式不一样。如果是普通的命令行方式,输出到stderr。如果是图形应用,估计会跳出一个窗口吧!程序最后会调用一个abort,结束程序。当然,进程都结束了,msbuf会自动释放,没必要手工释放了。


Interesting!!




0 0
原创粉丝点击