断言(通常)仅用于调试
“断言”的问题在于它通常位于调试二进制文件中,并且一些开发人员使用它们时就好像代码仍在生产中一样。
这本身并不邪恶,因为代码应该经过密集测试,因此产生断言的错误肯定会被发现并删除。
但有时(大多数时候?),测试并不像想要的那样密集。我不会谈论直到最后一刻我们必须编码的旧工作(不要问......有时,经理只是......嗯......)......您添加到代码中的断言有什么意义,该代码将在下一分钟被编译并作为发布二进制文件交付给客户端?
在(某些)现实生活应用中断言
在我们的团队中,我们需要一些东西来检测错误,同时需要其他东西来处理错误。我们可能在 Release Build 中需要它。
Assert 只会在调试构建时检测和处理错误。
所以我们添加了一个 XXX_ASSERT 宏和一个 XXX_RAISE_ERROR 宏。
XXX_ASSERT 宏的作用与 ASSERT 宏相同,但它会在 Debug 和 Release 中构建。它的行为(写日志、打开消息框、什么都不做等)可以由 .INI 文件控制,然后它会中止/退出应用程序。
这被用作:
bool doSomething(MyObject * p)
{
// If p is NULL, then the app will abort/exit
XXX_ASSERT((p != NULL), "Hey ! p is NULL !") ;
// etc.
}
XXX_RAISE_ERROR 宏只会“记录”错误,但不会尝试处理它。这意味着它可以将消息记录在文件中和/或打开带有消息的 MessageBox 和一个按钮继续,另一个按钮启动调试会话(根据 .INI 文件配置)。这被用作:
bool doSomething(MyObject * p)
{
if(p == NULL)
{
// First, XXX_RAISE_ERROR will alert the user as configured in the INI file
// perhaps even offering to open a debug session
XXX_RAISE_ERROR("Hey ! p is NULL !") ;
// here, you can handle the error as you wish
// Than means allocating p, or throwing an exception, or
// returning false, etc.
// Whereas the XXX_ASSERT could simply crash.
}
// etc.
}
在我们的库中引入它们一年后,只使用了 XXX_RAISE_ERROR。当然,它不能用于应用程序的时间关键部分(我们有一个 XXX_RAISE_ERROR_DBG),但在其他任何地方,它都很好。并且可以使用任何首选的错误处理,并且可以在开发人员计算机、测试人员甚至用户上随意激活它,这一点非常有用。