【游戏编程精粹】Assert

1、格式

Assert(条件表达式)

2、表现

条件表达式为false时,弹出一个警告对话框。你可以忽略这个断言并继续执行你的代码、中断程序,或者直接中断到断言失败的代码。

3、特点

Assert宏不会被编译到最终发布版本,因此可以在开发期间大范围使用断言。

4、使用法则

不要在断言中调用函数或者修改任何变量,否则你的调试和发行版本将有不同的行为,导致难以预料的严重后果。

5、技巧

(1)一般我们是在assert内部写条件表达式。这样做能捕获异常情况,但是无法给开发人员提供更多的信息,我们可以在assert括号内写字符串,比如assert(length != 0 && “lenght equal zero”);

(2)有时我们会在代码运行不到的地方加一个assert(0),我们可以使用相同的技巧,通过简单的取反字符串导致失败来插入描述字符串。assert(!"The code shoule be never get here");

(3)前面两个技巧可以通过写一个简单的宏合并到一起。这个宏接受两个参数,第一个参数是需要计算的条件表达式,第二个参数是描述字符串。它模拟了前两个技巧,但便于输入和阅读。

  #define Assert(a,b) assert(a && b)

  使用:

  Assert(src != 0, "lenght equal zero");

(4)标准c的断言会中断到assert.c文件中,而不是我们程序中断言出现的行。通过编写自己的assert宏,可以直接中断到输入断言的行

  

#if defined(_DEBUG)
extern bool CustomAssertFunction(bool, int, char*, char*);
#define Assert(exp,description)\
    if(CustomAssertFunction((bool)(exp),description,__FILE__,__LINE__))\
    {_asm{int 3}}
#else
#define Assert(exp,description)
#endif
bool CustomAssertFunction(bool, int, char*, char*)
{
    ...
}

(5)自己实现断言函数,还有其他好处。比如我们可以为自己的断言对话框添加一个总是“忽略”的选项,省的同一个断言触发几十次上百次,点都点不完。

        实现方式:在函数内添加一个静态变量,通过这个变量决定是否执行:

  if(CustomAssertFunction((bool)(exp),description,__FILE__,__LINE__))\

   {_asm{int 3}}

(6)如果触发了一个基础函数内的断言,我们无法确定问题具体出现在哪,因为调用该函数的地方太多了。一个简单的办法就是在断言对话框中提供堆栈信息。

  在Windows环境下,可以在断言对话框中提供一个按钮完成将信息复制到剪贴板的工作。只需要点几下鼠标,任何人都能轻松复制和粘贴assert到电子邮件或者错误报告中。

    if (OpenClipboard(NULL))
    {
        HGLOBAL hMem;
        char szAssert[256];
        char * pMem;

        sprintf(szAssert, "Put assert info here");
        hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(szAssert) + 1);

        if (hMem)
        {
            pMem = (char*)GlobalLock(hMem);
            strcpy(pMem, szAssert);
            GlobalUnlock(hMem);
            EmptyClipboard();
            SetClipboardData(CF_TEXT, hMem);
        }

        CloseClipboard();
    }

 

 
posted @ 2021-07-14 10:17  海贼~王路飞  阅读(139)  评论(0)    收藏  举报