C++调试过程详解:从问题识别到解决方案

概述

假设你已经编写了一个程序,但它没有正确工作——代码编译没有问题,但当你运行它时,你得到了一个错误的结果。你一定在某个地方有一个语义错误。你如何找到它?如果你遵循最佳实践,编写少量代码然后进行测试,你可能对你的错误所在有很好的了解。或者你可能完全没有头绪。

所有的bug都源于一个简单的前提:你认为正确的东西,其实并不正确。实际上找出错误所在可能具有挑战性。在这一课中,我们将概述调试程序的一般过程。

因为我们还没有涉及太多的C++主题,本章中的示例程序将会相当基础。这可能会让这里展示的一些技巧看起来过于繁琐。然而,请记住,这些技巧旨在用于更大、更复杂的程序,并且在这样的设置中(也就是你最需要它们的地方)会更有用。

调试的一般方法

一旦问题被识别,调试问题通常包括六个步骤:

  1. 找到问题的根本原因(通常是代码行不工作的地方)。我们将在下一课讨论如何做到这一点的一些策略。
  2. 确保你理解为什么会出现这个问题
  3. 确定你将如何修复这个问题
  4. 修复导致问题的问题
  5. 重新测试以确保问题已被修复
  6. 重新测试以确保没有出现新问题

现实生活中的调试类比

让我们用一个现实生活中的类比。假设一天晚上,你去冷冻室的冰柜里取一些冰。你把杯子放在冰柜下面,按下杠杆,然后……什么也没有出来。哦哦。你发现了某种缺陷。你会怎么做?你可能会开始一项调查,看看是否能找到问题的根本原因。

步骤1:找到根本原因

因为你听到冰柜试图送出冰,所以可能不是冰的输送机制本身。所以你打开冷冻室,检查冰盘。没有冰。这是问题的根本原因吗?不,这是另一个症状。在进一步检查后,你确定制冰机似乎没有制造冰。问题是制冰机还是别的什么?冷冻室仍然很冷,水管没有堵塞,其他一切似乎都在工作,所以你得出结论,根本原因是制冰机无法正常工作。

步骤2:理解问题

在这种情况下,这很简单。一个坏掉的制冰机不会制造冰。

步骤3:确定一个修复方案

在这一点上,你有几个修复选项:

  • 你可以绕过这个问题(从商店购买冰块)
  • 你可以尝试进一步诊断制冰机,看看是否有可以修复的部分
  • 你可以购买一个新的制冰机并安装在当前的一个位置
  • 或者你可以买一个新的冷冻室

你决定购买一个新的制冰机。

步骤4:修复问题

一旦制冰机到达,你安装它。

步骤5:重新测试

在重新打开电源并等待一夜后,你的新制冰机开始制造冰。没有发现新问题。

应用到编程中的调试过程

现在让我们将这个过程应用到上一课的简单程序中:

#include <iostream>

int add(int x, int y) // 这个函数应该执行加法
{
    return x - y; // 但由于使用了错误的操作符而没有
}

int main()
{
    std::cout << "5 + 3 = " << add(5, 3) << '\n'; // 应该产生8,但产生了2

    return 0;
}

这段代码在一方面很好:bug非常明显,因为错误的答案通过第10行打印在屏幕上。这为我们的调查提供了一个起点。

步骤1:找到根本原因

在第10行,我们可以看到我们传入的是字面量参数(5和3),所以那里没有错误空间。由于函数add的输入是正确的,但输出不是,很明显函数add必须产生了错误的值。函数add中唯一的语句是返回语句,它一定是罪魁祸首。我们已经找到了问题行。现在我们知道了应该关注的地方,注意到我们是在减去而不是加上,这是你通过检查很可能会发现的。

步骤2:理解问题

在这种情况下,很明显为什么会产生错误的值——我们使用了错误的操作符。

步骤3:确定一个修复方案

我们只需将操作符-更改为操作符+

步骤4:修复问题

实际上就是将操作符-更改为操作符+,并确保程序重新编译。

步骤5:重新测试

在实施更改后,重新运行程序将表明我们的程序现在产生了正确的值8。对于这个简单的程序来说,这就是所需的所有测试。

总结

这个例子是微不足道的,但它说明了你在诊断任何程序时将经历的基本过程。

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"