章节回顾
语法错误 是指你编写了一个不符合 C++ 语言语法规则的语句时发生的错误。编译器会捕获这些错误。
语义错误 是指语句在语法上是有效的,但没有实现程序员的意图。
调试 是指从程序中查找并移除错误的过程。
我们可以使用一个五步流程来处理调试:
- 找到根本原因。
- 理解问题。
- 确定修复方法。
- 修复问题。
- 重新测试。
通常,找到错误是调试中最困难的部分。
静态分析工具 是分析你的代码并寻找可能表明代码存在问题的语义问题的工具。
能够可靠地重现问题,是调试的第一步,也是最重要的一步。
我们可以使用以下策略来帮助查找问题:
- 注释掉代码。
- 使用输出语句验证代码流程。
- 打印值。
当使用打印语句进行调试时,使用std::cerr
而不是std::cout
。但更好的是,避免通过打印语句进行调试。
日志文件 是记录程序中发生的事件的文件。将信息写入日志文件的过程称为日志记录。
重构 是指在不改变代码行为的情况下重新组织代码的过程。这通常是为了使程序更加有组织、模块化或性能更优。
单元测试 是一种软件测试方法,通过这种方法测试源代码的小单元以确定它们是否正确。
防御性编程 是一种技术,程序员通过这种方式试图预见软件可能被滥用的所有方式。这些滥用通常可以被检测出来并加以缓解。
程序中跟踪的所有信息(变量值、哪些函数已被调用、当前的执行点)都是程序状态的一部分。
调试器 是一种工具,它允许程序员控制程序的执行,并在程序运行时检查程序状态。集成调试器 是集成到代码编辑器中的调试器。
单步执行 是一组相关调试功能的名称,它允许你逐条语句地执行代码。
- 进入函数:按程序的正常执行路径执行下一条语句,然后暂停执行。如果语句包含函数调用,进入函数会使程序跳到被调用函数的顶部。
- 跳过函数:按程序的正常执行路径执行下一条语句,然后暂停执行。如果语句包含函数调用,跳过函数会执行该函数并在函数执行完毕后将控制权交还给你。
- 退出函数:执行当前正在执行的函数中剩余的所有代码,然后在函数返回时将控制权交还给你。
- 运行到光标位置:执行程序,直到执行到达光标所选的语句。
- 继续:运行程序,直到程序终止或遇到断点。开始 与继续相同,只是从程序的开头开始。
- 断点:是一个特殊的标记,它告诉调试器在达到断点时停止程序的执行。
- 设置下一条语句:允许我们将执行点更改为其他语句(有时非正式地称为跳转)。这可以用来向前跳转执行点并跳过一些原本会执行的代码,或者向后跳转并重新执行已经执行过的内容。
- 监视变量:允许你在调试模式下程序执行时检查变量的值。监视窗口允许你检查变量或表达式的值。
- 调用堆栈:是一个列表,列出了所有被调用以到达当前执行点的活动函数。调用堆栈窗口是一个调试器窗口,它显示调用堆栈。
测验时间
问题 #1
以下程序本应添加两个数字,但无法正常工作。
使用集成调试器逐步执行此程序并监视x
的值。根据你学到的信息,修复以下程序:
#include <iostream>
int readNumber(int x)
{
std::cout << "Please enter a number: ";
std::cin >> x;
return x;
}
void writeAnswer(int x)
{
std::cout << "The sum is: " << x << '\n';
}
int main()
{
int x {};
readNumber(x);
x = x + readNumber(x);
writeAnswer(x);
return 0;
}
显示答案
问题 #2
以下程序本应除以两个数字,但无法正常工作。
使用集成调试器逐步执行此程序。对于输入,输入 8 和 4。根据你学到的信息,修复以下程序:
#include <iostream>
int readNumber()
{
std::cout << "Please enter a number: ";
int x {};
std::cin >> x;
return x;
}
void writeAnswer(int x)
{
std::cout << "The quotient is: " << x << '\n';
}
int main()
{
int x{ };
int y{ };
x = readNumber();
x = readNumber();
writeAnswer(x/y);
return 0;
}
显示答案
问题 #3
当执行点在第 4 行时,以下程序的调用堆栈是什么样的?对于这个练习,只需要函数名称,不需要表示返回点的行号。
我们在第 3.9 节 — 使用集成调试器:调用堆栈中讨论了调用堆栈。
#include <iostream>
void d()
{ // here
}
void c()
{
}
void b()
{
c();
d();
}
void a()
{
b();
}
int main()
{
a();
return 0;
}
显示答案
问题 #4
额外加分:以下程序本应添加两个数字,但无法正常工作。
使用集成调试器逐步执行此程序。对于输入,输入 8 和 4。根据你学到的信息,修复以下程序:
#include <iostream>
int readNumber()
{
std::cout << "Please enter a number: ";
char x{};
std::cin >> x;
return x;
}
void writeAnswer(int x)
{
std::cout << "The sum is: " << x << '\n';
}
int main()
{
int x { readNumber() };
int y { readNumber() };
writeAnswer(x + y);
return 0;
}
显示答案
作者注
鉴于到目前为止所涵盖的有限内容,很难找到具有非显而易见问题的简单程序的例子。读者有任何建议吗?