ASSERT

http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/

 

1

#define POW2_ASSERT(x) \ 

    if (!x) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } 

这是最一开始的样子

 

那么POW2_ASSERT(true || false); 

就会变成

if (!true || false) { pow2::Assert::Fail(...); } 

 

2

所以加括号:

#define POW2_ASSERT(x) \ 

    if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } 

 

那么

if (x == 3) 

    POW2_ASSERT(y == 4); 

else 

    DoSomethingReallyImportant(); 

就会变成

if (x == 3) 

    if (!(y == 4)) 

        pow2::Assert::Fail(...); 

    else 

        DoSomethingReallyImportant(); 

破坏了if else

 

3

所以把宏定义用do { … } while(0)包起来

 

于是就变成了:

#define POW2_ASSERT(x) \ 

    do { if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } } while(0) 

 

如果要写成带有宏开关,设定是否要开启assert的情况:

#ifdef POW2_ASSERTS_ENABLED 

    #define POW2_ASSERT(x) \ 

        do { if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } } while(0) 

#else 

    #define POW2_ASSERT(x) 

#endif 

我们设置为不开启

然后像这样调用

const bool success = DoStuff();  POW2_ASSERT(success); 

某些环境下会产生warning:

main.cpp(7) : warning C4189: 'success' : local variable is initialized but not referenced

 

 

4 所以我们把它转换成void

#define POW2_ASSERT(x) do { (void)(x); } while(0) 

 

那么如果

int main(int, char*[]) 

    bool DoStuff(); // comes from another .cpp file 

    POW2_ASSERT(DoStuff()); 

    return 0; 

编译器不知道DoStuff是什么,gcc下它会被调用

虽然warning被消除了但是有副作用

那么怎么能保证不执行DoStuff呢?

我们给它加一个 sizeof

 

5 于是

#ifdef POW2_ASSERTS_ENABLED 

    #define POW2_ASSERT(x) \ 

        do { if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } } while(0) 

#else 

    #define POW2_ASSERT(x) \ 

        do { (void)sizeof(x); } while(0) 

#endif 

 

 

6 有的时候我们希望assert了之后还可以continue

就需要我们自己定义handler来替换__debugbreak() 

dt里面的写法:

 

/// An assertion failure function.

//  @param[in]      expression  asserted expression.

//  @param[in]      file  Filename of the failed assertion.

//  @param[in]      line  Line number of the failed assertion.

///  @see dtAssertFailSetCustom

typedef void (dtAssertFailFunc)(const char* expression, const char* file, int line);

 

/// Sets the base custom assertion failure function to be used by Detour.

///  @param[in]     assertFailFunc  The function to be invoked in case of failure of #dtAssert

void dtAssertFailSetCustom(dtAssertFailFunc *assertFailFunc);

 

/// Gets the base custom assertion failure function to be used by Detour.

dtAssertFailFunc* dtAssertFailGetCustom();

 

#   include <assert.h>

#   define dtAssert(expression) \

        { \

            dtAssertFailFunc* failFunc = dtAssertFailGetCustom(); \

            if(failFunc == NULL) { assert(expression); } \

            else if(!(expression)) { (*failFunc)(#expression, __FILE__, __LINE__); } \

        }

 

#endif

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值