C++中的assert

基本概念

在 C++ 中,assert 是一个用于在程序运行时进行调试的宏。它主要用于检测程序中的假设条件是否为真,以帮助开发者发现并定位错误。assert 通常在调试阶段使用,而在发布(release)版本中会被禁用,从而避免对性能产生影响。

基本用法

要使用 assert,需要包含头文件 <cassert>

#include <cassert>

然后,可以在代码中使用 assert 宏来检查一个表达式是否为真。例如:

#include <cassert>
#include <iostream>

int factorial(int n) {
    assert(n >= 0); // 确保 n 是非负数
    if (n == 0) return 1;
    return n * factorial(n - 1);
}

int main() {
    int number = 5;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;

    number = -3;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl; // 这里会触发断言
    return 0;
}

输出如下:
img

在上述代码中,当 factorial 函数被调用时,如果传入的参数 n 为负数,assert(n >= 0); 将会触发断言失败,程序会中止执行并输出错误信息。

工作原理

  • 调试模式:在调试模式下(通常未定义 NDEBUG 宏),assert 会检查表达式的真假。如果表达式为假,程序会输出错误信息并调用 abort() 函数终止程序。

  • 发布模式:在发布模式下(通常定义了 NDEBUG 宏),所有的 assert 语句都会被忽略,编译器会将其移除。这意味着在发布版本中,assert 不会对性能产生任何影响。

要在发布模式中禁用 assert,可以在编译时定义 NDEBUG 宏,例如:

g++ -D NDEBUG -o my_program my_program.cpp

补充(使用NDEBUG宏)

在代码中定义NDEBUG宏

直接在代码中定义DEBUG宏时,如下:

#include <cassert>
#include <iostream>

#define NDEBUG

int factorial(int n) {
    assert(n >= 0); // 确保 n 是非负数
    if (n == 0) return 1;
    return n * factorial(n - 1);
}

int main() {
    int number = 5;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;

    number = -3;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl; // 这里会触发断言
    return 0;
}

输出如下:
img

尽管定义了 NDEBUG 宏,但断言 (assert) 仍然触发错误输出。

是不是很奇怪?

其实是个顺序问题。

assert 宏的行为取决于 NDEBUG 宏是否在包含 <cassert> 之前被定义。

由于在包含 <cassert> 之后才定义 NDEBUG,预处理器在处理 #include <cassert> 时,NDEBUG 还未被定义,因此 assert 宏仍然处于启用状态。这导致即使在代码中定义了 NDEBUG,断言依然会生效。

如何解决这个问题呢?

正确代码如下:

#define NDEBUG

#include <cassert>
#include <iostream>

int factorial(int n) {
    assert(n >= 0); // 确保 n 是非负数
    if (n == 0) return 1;
    return n * factorial(n - 1);
}

int main() {
    int number = 5;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;

    number = -3;
    std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl; // 这里会触发断言
    return 0;
}

在Visual Studio不启动调试输出如下:

img

在Visual Studio启动调试是这样的:

img

要将 #define NDEBUG 放在include <cassert> 之前

通过编译器选项定义 NDEBUG:

比如:

g++ -D NDEBUG -o my_program my_program.cpp
posted @   hisun9  阅读(293)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示