zoukankan      html  css  js  c++  java
  • C++ 断言

    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不是常量,静态断言是不符合语法的。

  • 相关阅读:
    正则表达式
    寒假第三天
    起航
    写正则表达式心得(一)
    80后偷偷“变老”的20种表现
    数据库三大范式
    给从表添加主键。数据库备份方法
    appletouchicon 和 appletouchiconprecomposed的区别
    一些对前端开发有用的网站
    背景图可以随时自动调整大小jquery插件backstretch
  • 原文地址:https://www.cnblogs.com/swarmbees/p/5621594.html
Copyright © 2011-2022 走看看