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

猜你喜欢

转载自blog.csdn.net/icebergliu1234/article/details/80322380