我正在教授一门将使用 C++ 的编程类(class)。我正在整理一份关于如何使用调试器的讲义,并希望让学生逐步执行这个用于名字和姓氏的哈希码生成器:
int nameHash(string first, string last){
/* This hashing scheme needs two prime numbers, a large prime and a small
* prime. These numbers were chosen because their product is less than
* 2^31 - kLargePrime - 1.
*/
static const int kLargePrime = 16908799;
static const int kSmallPrime = 127;
int hashVal = 0;
/* Iterate across all the characters in the first name, then the last
* name, updating the hash at each step.
*/
for (char ch: first + last) {
/* Convert the input character to lower case, then make sure it's
* between 0 and the small prime, inclusive.
*/
ch = tolower(ch) % (kSmallPrime + 1);
hashVal = (kSmallPrime * hashVal + ch) % kLargePrime;
}
return hashVal;
}
使用 gdb,我在包含基于范围的 for 循环的行上设置了一个断点:
(*) for (char ch: first + last)
当我用 gdb 运行程序时,正如预期的那样,它在这里触发了一个断点。但是,如果我继续执行,断点不会重新触发,程序会运行到完成。
我可以在我的系统上一致地重现此行为。如果我在循环体内设置一个断点并运行直到它被击中,如果我随后在循环顶部添加一个断点并点击“继续”,调试器将跳过循环断点。
我假设这可能是因为基于范围的 for 循环扩展为一系列不同的初始化步骤(我实际上可以看到在我的调试窗口中生成的临时变量)并且在初始化时设置了断点步骤而不是循环步骤。如果是这样的话,这是可以理解的,但出人意料地违反直觉。
我目前针对此问题的解决方法是在循环内的第一条语句而不是循环顶部设置断点,但这是违反直觉的,而且从教学的角度来看,这是非常糟糕的建议。
我的问题如下:
- 我的分析是否正确?
- 这是否特定于我的 gdb 版本?我正在使用
- Ubuntu 16.04 和
- g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609。 有
- 有没有办法让 gdb 将基于范围的 for 循环上的断点视为循环体上的断点,而不是初始化步骤?
最佳答案
您期望源代码和执行的一对一映射并不完全存在。 for
行不会在每次循环迭代时“重复”;它仅介绍和描述循环将如何运行。
for
行上的断点只会命中一次,这是预期的行为。我不记得曾经使用过 C、C++、JavaScript,以及任何工作方式不同的调试器。
将断点放在正文的第一行;重复的是 body 。
关于c++ - 继续基于范围的 for 循环不会重新触发断点吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41351600/