为什么这是使assert
宏仅在调试配置中有用的常规做法?如果可以测试不变式和检测编码错误,那么继续进行生产软件的同样蓬勃发展,难道不是一件容易的事吗?
我有一些S60背景,并且存在__ASSERT_ALWAYS
和__ASSERT_DEBUG
,后者等效于assert
。
检查断言费用。您可能不想在最终产品中进行额外的操作。如果断言总是奏效的,那么人们将开始减少使用它们以“不会破坏性能”。相信我,有很多人认为额外的检查是[[Performance kill]],他们会避免使用。这些是实际上必须更多使用断言的人!更重要的原因是,assert
如果失败,只会中止您的程序。这对于最终用户毫无用处。如果要使程序实际上以一条消息终止或执行一些有用的操作,则必须编写自己的断言。在这种情况下,您当然也可以选择将其保持在发布模式。最后,断言可以帮助您发现错误,尤其是隐藏的错误,但是在软件执行过程中,它们实际上可能不会发生。想象以下代码:
struct X
{
// other stuff
int stage;
};
X x;
... do some stuff
assert(x.stage == STAGE_2);
x.stage = STAGE_3; // go to next stage
... do more stuff
在这样的示例中,您的逻辑说x
应该在STAGE_2
中。如果不是,那是一个错误。但是,如果删除断言,修复x.stage
并继续进行,则希望该错误不太严重。在这种情况下,最终用户实际上可以继续工作而无需注意。如果您也将assert
设置为发布模式,则将迫使该人员退出没有任何可见效果的错误。
实际上,您一直在获取软件更新,因为它们声称已修复了错误。其中一些确实是assert
可能会发现的错误。但是,作为最终用户的您没有任何问题,实际上很高兴您没有因为这些assert
而受到打扰,不是吗?
这会使您的代码运行速度变慢。它使最终的可执行文件更大。
您要交付您测试的
但是当您将软件部署给客户时呢?我们不希望应用程序崩溃只是因为配置文件。对这种恐惧的一种反应是禁用断言在现场。
不要那样做!请记住,在客户的网站是通过您的测试过程完成的。你可能会复制它有麻烦。这些错误最难发现,并且适当说明问题的断言可以为您节省几天的时间努力。另一件事-在C ++中,您可以使用BOOST_ASSERT将其设置为在断言失败时引发异常,这使处理断言并可能从断言失败中恢复更加有用。我们将其与MadExcept结合使用,以便用户可以轻松地将字段中的任何断言故障发布到我们的错误跟踪器中,包括完整的调用堆栈,屏幕截图以及您所拥有的一切。
assert
起作用,除非您明确将其关闭。 (通常)没有甚至在“发布”版本中也要关闭它的原因,并且大多数我提供的已发布代码已激活assert
。关闭它的主要原因是性能。在这种情况下,您在性能很强的函数中非常本地地将其关闭关键,类似于:
#ifdef TURNOFFCRITICALASSERTS #define NDEBUG #include <assert.h> #endif // Function with critical code here... #undef NDEBUG #include <assert.h>
这是C标准委员会设计使用
assert
的方式。通常,不应该像这样在本地定义NDEBUG
。
这会使您的代码运行速度变慢。
#ifdef TURNOFFCRITICALASSERTS
#define NDEBUG
#include <assert.h>
#endif
// Function with critical code here...
#undef NDEBUG
#include <assert.h>