3-2 调试过程

假设你写了一个程序,但它运行不正常——代码编译通过,运行时却得到错误结果。这说明某个地方存在语义错误。如何定位错误?如果你遵循最佳实践,采用小步编写加测试的开发模式,或许能大致锁定问题所在;也可能完全毫无头绪。

所有错误都源于一个简单前提:你认为正确的东西其实是错误的。而真正找出错误所在往往充满挑战。本节课我们将概述程序调试的一般流程。

由于目前尚未涉及太多C++主题,本章示例程序将保持基础性。这可能使某些技术手段显得过度复杂。但请谨记:这些技术正是为大型复杂程序设计的,在实际应用中(即你最需要它们的场景)将发挥更大价值。


调试的一般方法

一旦发现问题,调试过程通常包含六个步骤:

  1. 找出问题的根本原因(通常是导致故障的代码行)。我们将在下一课讨论实现此目标的策略。
  2. 确保理解问题发生的原因。
  3. 确定修复问题的方案。
  4. 修复导致问题的故障点。
  5. 重新测试以确认问题已解决。
  6. 再次测试以确保未引发新问题。

让我们用生活类比说明:假设某晚你打开冰箱取冰,将杯子对准出冰口按下按钮——冰块却毫无动静。糟糕,你发现了故障。你会怎么做?很可能开始排查以找出问题根源。

找出根本原因:既然能听到制冰机试图送冰的声音,问题很可能不在于送冰装置本身。于是你打开冷冻室,检查冰格。没有冰块。这是问题的根源吗?不,这只是另一个症状。经过进一步检查,你发现制冰机似乎没有制冰。问题出在制冰机还是其他地方?冷冻室温度正常,进水管未堵塞,其他功能均运行良好,因此你得出结论:根本原因在于制冰机失效。

理解问题:此情况很简单。故障制冰机无法制冰。

确定解决方案:此时有几种选择:可采取临时措施(从商店购买袋装冰);可进一步诊断制冰机故障,查看是否有可修复的部件;可购买新制冰机替换现有设备。或直接更换整个冷冻柜。你最终决定购买新制冰机。

修复故障:新制冰机送达后立即完成安装。

复测验证:恢复供电并静置过夜后,新制冰机开始正常制冰,未发现新问题。

现在让我们将此流程应用于上一课的简单程序

#include <iostream>

int add(int x, int y) // this function is supposed to perform addition
{
    return x - y; // but it doesn't due to the wrong operator being used
}

int main()
{
    std::cout << "5 + 3 = " << add(5, 3) << '\n'; // should produce 8, but produces 2

    return 0;
}

这段代码有一个优点:错误非常明显,因为错误的答案通过第10行被打印到屏幕上。这为我们的排查提供了起点。

找出根本原因:在第10行,我们可以看到参数传递的是字面量(5和3),因此这里不可能出错。既然函数add的输入正确而输出错误,显然问题出在add函数内部。该函数中唯一的语句就是return语句,这必然是罪魁祸首。我们已锁定问题行。既然明确了关注点,通过检查发现“减法操作取代了加法”这一错误就变得显而易见了。

理解问题:在此案例中,错误值产生的原因显而易见——我们使用了错误的运算符。

确定解决方案:只需将 operator- 替换为 operator+。

修复问题:实际操作是将 operator- 替换为 operator+,并确保程序重新编译。

重新测试:实施修改后,再次运行程序将显示正确结果8。对于此类简单程序,测试至此已足够。

此例虽简单,却完整展现了诊断任何程序时需经历的基本流程。

image

posted @ 2026-02-10 16:10  游翔  阅读(1)  评论(0)    收藏  举报