4
ASSERT(pointer);
pointer->x;

在这段代码中, ASSERT 似乎是多余的。如果指针为 NULL,pointer->x 无论如何都会失败。我的论点正确吗?

4

7 回答 7

33

断言的重要(如果不是主要)目的是记录应该在代码中的某个点保持的不变量。如果不变量被破坏,也可以中止程序的事实assert只是锦上添花,尽管它非常有用。我想说,在一个典型的程序中,90% 的断言是显然不会失败并且永远不会失败的断言。换句话说,assert在很大程度上是一种形式化的评论语言。从某种意义上说,这些“注释”是用与其余代码(C/C++)相同的语言编写的,而不是简单的英语。

在您的代码示例中,断言在那里告诉您指针不应该在这里为空。这就是它存在的原因。从这个意义上说,这assert不是多余的。

就执行流程而言,assert总是多余的,这就是为什么断言通常不会在代码的发布版本中编译。没有什么可以阻止您在发布代码中保留断言,但通常是通过引入一种特殊的“发布断言”来完成的。在任何情况下,使代码的主要功能依赖于断言所采取的行动都不是一个好的编程习惯。就代码的主要功能而言,断言应该是多余的。

于 2009-12-23T23:41:26.867 回答
19

是的,但是pointer->x(我认为)会以不受控制的方式失败,而assert将会失败并告诉你确切的位置。

从某种意义上说,assert总是多余的,当然

于 2009-12-23T23:31:28.163 回答
3

不,这不是多余的。断言将在任何不好的事情发生之前停止执行。另一方面,如果你取消引用一个无效的指针,你可能会导致真正的损坏,或者至少是不受控制的段错误而不是受控的中止。

于 2009-12-23T23:32:17.570 回答
1

ASSERT不是 C 标准的一部分,所以可以是任何东西

 #define ASSERT(x) do { \
     x = malloc ( sizeof *x ); \
     memset ( x, 0, sizeof *x );\
     } while ( 0 )

assert是另一回事。

有些人有一个ASSERT调用调试器的宏,有些人有一个执行其他调试或日志记录的宏,并使用预处理器的字符串化功能。

您确实必须说出宏对任何人的作用,才能知道它是否重要。

于 2009-12-23T23:45:07.157 回答
0

在某些情况下,断言可用于调试 http://simonwillison.net/2008/May/22/debugging/

于 2009-12-23T23:33:54.417 回答
0

ASSERT也可用于检查可能不会导致崩溃的无效或不合逻辑的条件。这是一个非常人为的例子:

void cpu_hog(int duration)
{
    int start_time = (int) time(NULL);
    int end_time   = start_time + duration;

    ASSERT(end_time > start_time);  /* If this fails, "int" is too small. */

    while ((int) time(NULL) < end_time)
        ;
}

一个小提示:建议您使用它的大多数支持者ASSERT仅使用它来验证您在编写代码时所做的假设(例如,指针不是 NULL,或者条件不能发生)。通常认为使用捕获预期会发生的与用户相关的错误或异常(例如,磁盘已满)是一个主意,因为 (1)仅存在于调试版本中,并且 (2) 即使您提升了调试代码到生产时,它会崩溃而不是优雅地处理条件。ASSERTASSERT

于 2009-12-23T23:47:25.893 回答
-1

ASSERT 不会失败。此处用于在断点处停止调试器。这不会影响发布版本。

于 2009-12-23T23:35:36.690 回答