C++ 断言

摘要:
断言宏断言宏深度学习1。运行时断言1.1。断言属于运行时断言。您可以在运行时判断给定条件是否为真,如果为真,则不执行任何操作。否则,打印跳转错误消息,然后中止进程。)__asm{int3};//检查断言,然后如果断言结果为假,则调用内联汇编指令int3进入调试中断1.3。用户定义的断言实现函数:断言时可以支持变量输出SMART _ ASSERTvalue&&“Invalidvalue!静态断言的另一个优点是,当违反断言时,您可以自定义编译错误信息。

assert宏 (基本概念与用法整理)

assert宏的深入学习

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

#include

class Assert

{

public:

//编译期,SMART_ASSERT宏被替换,断言被命中时

//1、如果断言后跟有括号括起来的参数时

//SMART_ASSERT_C和SMART_ASSERT_N将不会被认为是成员,而是SMART_ASSERT_C(x)和SMART_ASSERT_N(x)宏

//间接替换为调用ShowMemoryValue成员方法。

//2、如果断言命中时后边无括号,则SMART_ASSERT_C被认为是成员变量;

//如果断言命中时后边括号在多次宏替换之后没有啦,则SMART_ASSERT_OP宏被替换后的最后一个.调用被认为是成员变量调用

Assert & SMART_ASSERT_C;

Assert & SMART_ASSERT_N;//SMART_ASSERT_C和SMART_ASSERT_N循环调用,来解析断言后边追加的参数

Assert( const wchar_t *wexpr

, const wchar_t *wfile

, const char * expr

, const char * file

, unsigned line)

: _Expr(wexpr)

, _File(wfile)

, _Line(line)

, _CFile(file)

, _Message(expr)

, SMART_ASSERT_C(*this)

, SMART_ASSERT_N(*this)

{

};

~Assert();

//如果需要支持打印多种数据类型,可以对该方法的第二个参数重载,或者对SMART_ASSERT_OP宏的进行修改,传入参数x时强制转换

为string类型

Assert & RestoreMemoryValue(const char * key, const std::string &val);

private:

std::wstring _Expr;//异常表达式

std::wstring _File;//文件名称

unsigned _Line;//文件行数

std::string_CFile;//文件名称

std::string_Message;//异常消息

std::map _memoryValue;//内存变量值

};

#ifdef SMART_ASSERT

#undef SMART_ASSERT

#endif

#define SMART_ASSERT_C(x)SMART_ASSERT_OP(x, N)

#define SMART_ASSERT_N(x)SMART_ASSERT_OP(x, C)

#define SMART_ASSERT_OP(x, next)

SMART_ASSERT_C.RestoreMemoryValue(#x, (x)).SMART_ASSERT_##next

#define SMART_ASSERT(expr)

if ( (expr) );

else Assert(_CRT_WIDE(#expr), _CRT_WIDE(__FILE__), #expr, __FILE__, __LINE__).SMART_ASSERT_C

//实现

////////////////////////////////////////////////////////////////////

#include

#include "SmartAssert.h"

//https://msdn.microsoft.com/zh-cn/library/9sb57dw4.aspx  :_wassert说明

Assert::~Assert()

{

//获取_memoryValue临时变量值打印

//进入中断

_wassert(_Expr.c_str(), _File.c_str(), _Line);

}

Assert & Assert::RestoreMemoryValue(const char *key, const std::string &val)

{

_memoryValue[key] = val;

return *this;

};

2、静态断言

    在2011年的C++标准中出现了静态断言(static_assert)的语法,所谓静态断言,就是在编译时就能够进行检查的断言,static_assert

是C++的标准语法,不需要引用头文件。静态断言的另一个好处是,可以自定义违反断言时的编译错误信息。

例如:

const int i = 22;

static_assert(i != 22, "i equals to 22");//这个代码,将无法通过编译,因为i的值违反了静态断言。

注意:静态断言的限制是,断言本身必须是常量表达式,如果这样的i不是常量,静态断言是不符合语法的。

免责声明:文章转载自《C++ 断言》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇mac mysql 使用注意事项自己写的身份证号码15位升18位的函数下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ubuntu13.04下gcc4.5.1的安装

(1)去gcc官网下载源码包http://ftp.gnu.org/gnu/gcc/gcc-4.5.1/gcc-4.5.1.tar.bz2 (2)编译安装gcc之前需要先安装三个库,如果下面命令行不通,对应的都可以到官网下载: $wgetftp://ftp.dti.ad.jp/pub/lang/gcc/infrastructure/gmp-4.3.2.tar...

dateutil

Date、long、Calendar之间的相互转换 //当前时间 Date date = DateUtil.date(); //当前时间 Date date2 = DateUtil.date(Calendar.getInstance()); //当前时间 Date date3 = DateUtil.date(System.currentTimeMillis...

Android中的<include>标签和<merge>标签

android开发中经常会碰到某一个布局的复用;直接拷贝粘贴并不是是有效的策略,这时候就能够借助<include>标签和<merge>标签来完毕。 官方文档: http://developer.android.com/training/improving-layouts/reusing-layouts.html 1. <...

linux 下nginx

所有的配置文件都在/etc/nginx (ect/nginx/nginx.conf) 下,并且每个虚拟主机已经安排在 了/etc/nginx/sites-available 程序文件在/usr/sbin/nginx 日志放在了/var/log/nginx中 并已经在/etc/init.d/下创建了启动脚本 nginx -------------------...

rootkit:实现隐藏进程

实现隐藏进程一般有两个方法: 1,把要隐藏的进程PID设置为0,因为系统默认是不显示PID为0的进程。 2,修改系统调用sys_getdents()。 Linux系统中用来查询文件信息的系统调用是sys_getdents,这一点可以通过strace来观察到,例如strace ls 将列出命令ls用到的系统调用,从中可以发现ls是通过getdents系统调用...

c++ 开源日志库选择

liblogger 待选为 glog、log4cplus、log4cpp、log4cxx 目前准备使用glog,使用方便,性能也不错,待进一步试验,如果有不能满足的功能就转用 log4cplus,功能很全面,不过稍复杂些。 其它两个都是三年前就没更新,没好感,暂不准备使用。 1.log4cplus 最新版本:1.1.0 2012-03-11 下载地址:ht...