Boost C++ assert的用法简析

12 篇文章 5 订阅

1 软件验证、测试宏assert

C/C++本身仅提供了有限的软件验证、测试宏assert,而Boost.assert库增强了assert库,包含如下的组件

  1. assert —>运行时检查
  2. static_assert —>编译时检查 已被C++17收录
  3. lightweight_test —>提供最基本的单元测试功能
  4. test —>提供最基本的单元测试功能,提供测试用例、测试套件等整个体系

2 assert运行时断言

BOOST_ASSERT等同于assert宏,断言为假发生异常。它还有一个特点
1. BOOST_ASSERT只会在Debug模式生效,在Release下不会进行编译。

# define BOOST_ASSERT(expr) 				assert(expr)
# define BOOST_ASSERT_MSG(expr, msg) 		assert((expr)&&(msg))

案例:

double fun(int x)
{
    BOOST_ASSERT_MSG(x != 0, "divided by zero");
    std::cout << "boost_assert: " << std::endl;
    return 1.0 / x;
}

断言失败时候的输出:

double fun(int): Assertion `(x != 0)&&("divided by zero")' failed.

2.1 禁用BOOST_ASSERT

如果引入了boost的assert,但是任然想用C++的assert,在头文件增加如下代码

#define BOOST_DISABLE_ASSERTS

通过查看代码可知,其实是让BOOST_ASSERTBOOST_ASSERT_MSG失效,即((void)0),将激活如下代码

# define BOOST_ASSERT(expr) ((void)0)
# define BOOST_ASSERT_MSG(expr, msg) ((void)0)

案例,这时候BOOST_ASSERT_MSG已经失效了哈。

double fun(int x)
{
    // 使用宏失效
    BOOST_ASSERT_MSG(x != 0, "divided by zero");
    std::cout << "boost_assert: " << std::endl;

    // 有效
    assert(x != 0 && "divided by zero");
    std::cout << "asssert: " << std::endl;

    return 1.0 / x;
}

2.2 自定义assert?

Boost.asssert提供很大的灵活性,程序员可以在出错的时候给出出错原因、文件名、行号、函数名。只需要在文件开始处提供如下代码,不过它带来一个缺点

  1. 断言表达式无论在Debug,还是release下都要求值!!!
#define BOOST_ENABLE_ASSERT_HANDLER

进而,会自动激活assertion_failed()assertion_failed_msg()这两个函数,因此,下面是一个Demo

#define BOOST_ENABLE_ASSERT_HANDLER
#include <iostream>
#include <boost/assert.hpp>
#include <boost/format.hpp>

namespace boost{
    void assertion_failed(char const * expr, char const * function, char const * file, long line)  // user defined
    {
        boost::format fmt("Assertion failed!\nExpression: %s\n"
                    "Function: %s\nFile: %s\nLine: %ld\n\n");
        fmt % expr % function % file % line;
        std::cout << fmt;
    }
    void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line) // user defined
    {
        boost::format fmt("Assertion failed!\nExpression: %s\n"
                          "Function: %s\nFile: %s\nLine: %ld\n"
                          "Msg: %s\n\n");
        fmt % expr % function % file % line % msg;
        std::cout << fmt;
    }
}

注意:

  1. 上面两个函数都应该写在boost库下
  2. expr是错误表达式、function是函数名、msg是错误信息、file是文件名、line是行号
  3. 这里使用的是format库,有机会在介绍,其实它很像printf(),尤其是%的使用,也是一摸一样的

如何调用呢?和上面两个是对应的

1. BOOST_ASSERT() 自动调用assertion_failed()
2. BOOST_ASSERT_MSG() 自动调用assertion_failed_msg()

一个案例输出

Assertion failed!
Expression: x != 0
Function: double fun(int)
File: /home/topeet/myBoost/chap6_assert/_6_1_3.cpp
Line: 27

3 static_assert编译时检查

static_assert表示在编译时就会进行断言,因此运行时不存在这个问题,这个对Debug和Release都不会有任何影响。

头文件是:

	#include <boost/static_assert.hpp>

同理,也有两个宏,其中一个支持输出错误信息

BOOST_STATIC_ASSERT(expr)
BOOST_STATIC_ASSERT_MSG(expr, msg)

下面是一个案例

template <typename T>
T my_min(T a, T b)
{
    BOOST_STATIC_ASSERT_MSG(sizeof(T) < sizeof(int), "only short or char");
    return a < b ? a : b;
}

测试代码

// 主函数,一个测试代码
	std::cout << my_min((short)1, (short)3) << std::endl;
	std::cout << my_min((long)1, (long)3) << std::endl;		// error 不管是什么编译器,long>=int,这是硬性规定

输出代码,编译直接报错

In instantiation of ‘T my_min(T, T) [with T = long int]:
required from here
static assertion failed: only short or char
     BOOST_STATIC_ASSERT_MSG(sizeof(T) < sizeof(int), "only short or char");

4 总结static_assert和assert

逐步运行和比较输出,你会很清楚的发现,如下规律

  1. static_assert是编译就会发现错误,assert是在运行时才会发现。
  2. 同时提供了两个函数,一个不带MSG,一个带有MSG。
  3. 提供一个自定义的assert,方便给出给出出错原因、文件名、行号、函数名

5 lightweight_test提供最基本的单元测试功能

你是否希望有如下的宏

BOOST_TEST(e)				断言是否成立
BOOST_TEST_NOT(e)			断言是否不成立
BOOST_ERROR(e)				断言失败输出错误信息s
BOOST_TEST_EQ(e1, e2)		断言e1==e2?
BOOST_TEST_NE(e1, e2)		断言e1!=e2?
BOOST_TEST_THROWS(e, eX)	断言失败,抛出异常
同时提供两个C-style语法的断言
BOOST_TEST_CSTR_EQ(e1, e2)		断言e1==e2?
BOOST_TEST_CSTR_NE(e1, e2)		断言e1!=e2?

无疑,lightweight_test组件给我们提供了完整的测试方案,你只需要包含头文件

#include <boost/core/lightweight_test.hpp>

注意的,必须用boost::report_errors()作为返回值,不然会发生异常
下面用shared_ptr做了一个简单的测试,

    {
        // 一个简单的测试用例
        boost::shared_ptr<int> p = boost::make_shared<int>(10);

        BOOST_TEST(*p == 10);
        BOOST_TEST(p.unique());
        BOOST_TEST_NOT(!p);
        BOOST_TEST_EQ(p.use_count(), 1);
        BOOST_TEST_NE(*p, 20);
        BOOST_ERROR("ERROR ACCURED!!!");			// error
    }
    return boost::report_errors();

输出如下

ERROR ACCURED!!! in function 'int main(int, char**)'
2 errors detected.

boost::report_errors()?
答:总结和报告错误,必须加上。至于是否加在返回值,其实无所谓,只要在返回值前即可。否则编译错误!!!

6 test组件

其实前面的组件丰富了C++的assert的功能,从测试角度将,这并不完整,因此test库填充了这个缺口,也像其他语言支持大型的测试工作。

Boost C++测试组件test库
https://blog.csdn.net/weixin_39956356/article/details/111385774

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值