【问题标题】:Use of Assert and NULL pointer validation what's better to use使用 Assert 和 NULL 指针验证哪个更好用
【发布时间】:2013-01-11 06:49:35
【问题描述】:

在进行编程时,我使用断言以及 NULL 指针验证。

但据我所知,断言仅在 DEBUG 模式下有用。

我的问题是假设我有一个内部指针,我确信它不能是 NULL 示例函数返回一个指针(但指针不是类的成员),在这种情况下我可以使用 assert

test* ptr = fun(); // return a pointer of type test
assert(ptr);

//do some operation

NULL指针验证

test* ptr = fun(); // return a pointer of type test
assert(ptr);
if (NULL != ptr)
{
    //do some operation
}

这里哪个代码实践是好的。据我了解,它将是第二个。 因为我遇到过一些情况,由于一些我们想不到的异常情况,ptr的值返回NULL

但是我们还有其他更好的选择吗?

【问题讨论】:

  • 为什么这个问题被投票赞成关闭?这是一个有效的问题。
  • 你考虑过不返回null吗?写代码会容易得多。 IE。空数组/特殊null objects 和异常可能会显着限制返回 null 并因此检查它的需要。
  • @AlexeiLevenkov 检查第二种情况
  • 如果你爱上了assert(),那么both一致。 assert(ptr && "Unexpected NULL pointer"); if (ptr) {...}。仅选择 assert() 会忽略您在发布版本中首先进行断言的原因,并且仅选择 if (ptr) 会隐藏您在调试版本中将要开始的迂腐。
  • @Amit0440 在 C 和 C++ 中,零表示 false,非零表示 true 用于布尔评估。老实说,在现在的多代 C 和 C++ 语言的这一点上,这是一个品味问题。给每个人他/她自己的。

标签: c++ visual-c++ assert


【解决方案1】:

assert 说“如果这不是真的,我的代码中存在逻辑错误”。如果您正在编写代码来处理指针可能为空的事实,那么断言调用是多余的。您应该将日志记录和处理添加到“其他”案例中。这样,您的调试版本将以与发布版本相同的方式运行,即使在空指针情况下也是如此。

如果您的意思是断言并且必须在空指针上中止,则在您的发布版本中启用断言或使用替代的启用发布的断言机制。

仅调试断言的唯一原因是检查在发布代码中成本太高而无法生成的逻辑错误。通常,对指针的空检查不属于此类。

【讨论】:

    【解决方案2】:

    真正的解决方案取决于函数fun 的语义。

    如果返回NULL在语义上是无效的,那么我认为fun应该抛出一个适当的异常(例如std::logic_error1)而不是返回NULL,你可以使用@呼叫站点上的 987654326@ 以确保 fun 工作正常,如果工作不正常,则中止程序。这样,fun 中的错误不会传播到程序的其余部分,因为它会立即被捕获。

    但是,如果从 fun 返回 NULL 在语义上是有效的,那么您应该使用 if 检查调用站点上的返回值,并且在这种情况下实际上不需要 assert,因为您将使用if 反正。

    1.或者你可以使用std::runtime_errorstd::domain_error

    【讨论】:

    • 一些异常情况可能会使 fun 的值返回为 NULL 或该变量的内存损坏。所以还有其他一些线程。这最终意味着强制我使用第二种情况...
    【解决方案3】:

    我建议您使用自己的代码进行断言。 正如您所说,断言仅在调试模式下有效。

    所以,如果它在发布模式下工作,它就不起作用。

    如果您使用自己的断言代码。您可以简单地找出问题所在。

    test* ptr = fun(); // return a pointer of type test
    MyOwnAssert(ptr); 
    
    void MyOwnAssert(void* pPointer)
    {
       if (NULL == pPointer)
         abort();
    }    
    

    【讨论】:

    • 在上面的代码中,你检查 NULL 而不是断言,我认为上面的代码可以通过使用 MACRO 而不是函数来简化
    【解决方案4】:

    正如您所提到的,断言仅在调试过程中,帮助程序员确定他们出错的地方。它在生产中没有任何价值,因此,如果您对指针可能为 NULL 有任何疑问,我更喜欢使用第二种方法。

    【讨论】:

    • 是的,我更喜欢第二种方法....但 fun() 理想情况下不能返回 NULL。所以不是额外的条件检查或总是在安全的情况下玩更安全的游戏:-)
    • 但是如果你在调试中有断言,你将永远不会测试指针为空的代码路径。这意味着如果它确实发生在生产环境中,那么后续代码路径将永远不会在指针为空的情况下进行测试,并且原始错误可能会被后续代码执行所掩盖。随后的代码执行可能会或可能不会从错误中恢复——这个事实永远无法被测试。
    • @CharlesBailey 我从来没有怀疑指针值是 NULL。
    • @Amit0440:我的评论是针对 KVRNKiran,他说他更喜欢第二种方法“如果您对指针可能为 NULL 有任何疑问”。
    【解决方案5】:

    您对 assert 所做的选择是您自己的选择:如果您愿意,可以在生产环境中使用。

    我想说,如果您想及早发现错误,使用 assert() 会更好。特别是如果它是一个 NULL 指针的事实不应该发生。
    您甚至可以在其中粘贴 Google Breakpad,这样每当您点击 NULL 指针时,您就会在该点发送带有完整堆栈的报告。

    在可能出现 NULL 指针的情况下(有时是预期的......),那么我猜 NULL 检查会更好。但我想说的是,此时你的代码在某种程度上是错误的,如果它必须适应被传递的 NULL 指针。

    【讨论】:

    • 您能用一个小样本详细解释一下 Google Breakpad 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    相关资源
    最近更新 更多