【问题标题】:assertions in native c++ / debugging本机 C++ / 调试中的断言
【发布时间】:2011-12-11 18:18:31
【问题描述】:

调试期间使用断言的示例:

char* append(char* pStr, const char* pAddStr)
{
    // Verify non-null pointers

    assert(pStr != nullptr);
    assert(pAddStr != nullptr);

    // Code to append pAddStr to pStr...
}

在一个简单的程序中调用带有空指针参数的 append() 函数在我的机器上产生了以下诊断消息:

Assertion failed: pStr != nullptr, file c:\beginning visual c++ 2010\examples visual studio project files\tryassertion\tryassertion\tryassertion.cpp, line 10

我想知道断言是否必要。如果我可以使用 if-else 表达式来输出我自己的错误消息,那么使用它们有什么意义?

【问题讨论】:

    标签: c++ debugging assertion


    【解决方案1】:

    断言条件检查;它只是一个类似这样的宏(简化):

    #define assert(b) if (!(b)) { std::cerr << ...; exit(1); }
    

    我能想到两个优点:

    1. 当您在发布模式(即非调试模式)下编译时,所有asserts 都将编译为空,因此您不会产生运行时开销。
    2. assert 是一个成语;其他程序员知道要寻找它们,它们也不同于“正常”的控制流。

    【讨论】:

      【解决方案2】:

      断言用于确保满足某些基本假设。基本上,您在“不可能发生”的每种情况下都添加一个断言,最常见的是断言必须如何使用 API,例如前置条件和后置条件(如您的示例,其中包含检查附加函数的正确使用的断言)。对于其他已知在运行时发生且无法事先预防的错误(例如,未找到文件或权限不足等错误),您将不得不编写错误处理代码。

      断言不包含在发布编译中,因此它们只能用于捕获在调试模式测试运行中已经发生的严重编程错误。

      【讨论】:

        【解决方案3】:

        当违反断言的唯一情况是程序逻辑中的错误时,您应该使用断言。您使用普通的if-then-else 条件来处理由于输入或外部可能条件(即文件丢失)而可能确实发生的事情。

        当您确定程序逻辑有问题时,尝试继续执行并没有多大意义......您的程序的工作方式与您的想法不同(因为否则不会触发断言)和因此,最好的选择就是大喊问题所在并立即死亡。

        当代码在“发布”模式下编译时,断言通常会被删除,但是如果程序逻辑非常复杂,并且如果继续执行产生错误输出会产生更大的问题,则保留它们可能是有意义的停止执行。

        请注意,有时新手程序员陷入断言的“陷阱”是,当断言代码被删除以用于发布模式时,断言中的表达式不再被评估,因此如果你的程序依赖于它的副作用表达式,那么您将有麻烦...例如:

        ...
        assert(insert_record(db, data) == DB_OK);  // <== this is bad
        ...
        

        当断言被定义时,插入根本不会发生,留下一个在发布模式下不起作用的程序,而当你尝试调试问题时它会起作用。

        【讨论】:

          猜你喜欢
          • 2015-06-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多