C++ 断言
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++ 断言的更多相关文章
- iOS-----程序异常处理----- 断言NSAssert()和NSParameterAssert区别和用处
NSAssert和assert是断言,主要的差别是assert在断言失败的时候只是简单的终止程序,而NSAssert会报告出错误信息并且打印出来.所以尽管的使用NSAssert,可以不去使用asser ...
- GO语言总结(5)——类型转换和类型断言
上一篇博客介绍了Go语言的数组和切片——GO语言总结(4)——映射(Map),本篇博客介绍Go语言的类型转换和类型断言 由于Go语言不允许隐式类型转换.而类型转换和类型断言的本质,就是把一个类型转换到 ...
- postman 断言解析
最近在学习postman官方文档, 顺势翻译出来,以供学习! postman断言是JavaScript语言编写的,在postman客户端指定区域编写即可. 断言会在请求返回之后,运行,并根据断言的pa ...
- 测试框架Mocha与断言expect
测试框架Mocha与断言expect在浏览器和Node环境都可以使用除了Mocha以外,类似的测试框架还有Jasmine.Karma.Tape等,也很值得学习. 整个项目源代码: 为什么学习测试代码? ...
- JavaScrict中的断言调试
今天在看忍者秘籍的时候,看到一个断言方法.查阅了一下资料,原来javascript中的console也包含这个方法.具体用法如下: <script type="text/javascr ...
- 断言与异常(Assertion Vs Exception)
在日常编程实践中,断言与异常的界限不是很明显,这也使得它们常常没有被正确的使用.我也在不断的与这个模糊的怪兽搏斗,仅写此文和大家分享一下我的个人看法.我想我们还可以从很多角度来区别断言和异常的使用场景 ...
- 断言(Assert)与异常(Exception)
断言是被用来检查非法情况而不是错误情况,即在该程序正常工作时绝不应该发生的非法情况,用来帮助开发人员对问题的快速定位.异常处理用于对程序发生异常情况的处理,增强程序的健壮性.容错性,减少程序使用中对用 ...
- Linux Kernel 代码艺术——编译时断言
本系列文章主要写我在阅读Linux内核过程中,关注的比较难以理解但又设计巧妙的代码片段(不关注OS的各个模块的设计思想,此部分我准备写在“深入理解Linux Kernel” 系列文章中),一来通过内核 ...
- selenium自动化-java-封断言类2
封装断言类 package streamax.com; import java.util.ArrayList; import java.util.List; import org.testng.Ass ...
- selenium自动化-java-封装断言
封装的断言. 1 package com.baidu.www; import org.testng.Assert; /* * 封装断言 */ public class assertion { stat ...
随机推荐
- ./graldew bash: ./gradlew: No such file or directory
使用gradlew的项目,可以使用./gradlew assembelDebug 使用本地gradle编译的项目,并且配置了环境变量,可以使用gradle assembleDebug直接编译包
- java创建文件写入内容,并实现下载该文件
public void getText(){ response.setHeader("Content-Disposition", "attachment;filename ...
- linux查看分区是否开启acl权限
1.为什么需要ACL权限 ACL的全称是 Access Control List (访问控制列表) .对于文件或者目录,都有相应的操作权限 r(read 读),w(write 写),x(execute ...
- 真正的ddos防御之道,简单干脆有效!
话说,30G 就各种发博客 BB,唉,坦白说 ,博客园团队真心没见过世面 来 各位 先看图 啥意思呢? 就是哥的 最高防御是 600G. 没错,基本对当时的游戏没啥大的影响,10秒内恢复. 因为时间 ...
- 邮件服务器 postfix
背景介绍 邮件服务器普遍需要一个主机名来使得mail from 以"账号@主机名"方式显示.由于外网上垃圾邮件太多,现在已不使用ip发邮件,很多网络供应商都会对来源不明的邮件进行限 ...
- C# CSV 文件转换成DataTable
{ DataTable dt = new DataTable(); FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess ...
- redis离线集群安装
用一个叫redis-trib.rb的ruby脚本.redis-trib.rb是redis官方推出的管理redis集群的工具,集成在redis的源码src目录下(redis-xxx/src/).是基于r ...
- 最简单的 nginx 负载均衡,只能演示,企业中最好不用
修改nginx.conf 配置,重启nginx即可 upstream 包名{ ip_hash; #使用此功能,权重和备份都不能使用!一台机器永远只连同一台机子 server IP:端口 weight= ...
- solr与Elasticsearch对比
搜索引擎:Solr与Elasticsearch比较分析 Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助你用前所未有的速度去处理大规模数据. 它可以用于全文搜索,结构化搜索以及分 ...
- 1 小时 SQL 极速入门(二)
上篇我们说了 SQL 的基本语法,掌握了这些基本语法后,我们可以对单表进行查询及计算分析.但是一个大的系统,往往会有数十上百张表,而业务关系又错综复杂.我们要查的数据往往在好几张表中,而要从多张表中来 ...