开关在意想不到的地方跳跃
a switch jumping in unexpected place
我已经分叉了一个C++项目,并在交换机中添加了一些案例。然后它在下一个案例的中间跳跃。条件为int
,事例值为 #define
d。由于代码很大,我在这里写一些等效且简单的东西:
#define AAA 1
#define BBB 2
int X::func(int i) {
bool b = (i == 5);
int v = (b ? 10 : 5);
switch (i) {
case AAA:
if (b && v > 4) {
v = v + 1;
return 0;
}
break;
case BBB:
if (!b || v > 40) {
v = v + 2;
b = false; // direct jump here from the switch for i = AAA
return 0;
}
break;
}
return -1;
}
如果我将 AAA 传递给 X::func,代码执行直接从 switch
跳到 BBB 案例内的b = false;
。在实际代码中,我有几十个案例,它发生在中间。如果我完全case BBB
评论,它会在评论中的同一位置跳跃!每个案例都以 break;
结尾,内部没有变量声明。就像这里的变量 b 和 v 一样,它们是在 switch 语句之前声明的。
部分案件处于#ifdef
#endif
块中。出现问题的其他情况在此块中。条件为 true,因此编译块。无论如何,我在抑制了这两个预编译器语句后对其进行了测试,并且是一样的。
如果我{}
添加括号以完全填充像这里这样的情况,我仍然有相同的结果:
case BBB: {
if (!b || v > 40) {
v = v + 2;
b = false; // direct jump here from the switch for i = AAA
return 0;
}
break;
}
一切都编译良好,并在调试会话或正常执行中执行相同的操作。我在Eclipse CDT Indigo下使用gcc 4.5.4。
它看起来像一个编译器错误,但可能是什么原因?
如果您通过调试器单步执行函数,则调试器中的"当前突出显示的行"不一定对应于当前正在执行的行(当涉及循环时,当优化打开时,当有很多宏时,等等)。
切换后将变量打印到 stdout/stderr,并查看它们的值是否正确。还要在两个cases
中将一些调试行打印到 stdout/stderr。如果您得到的输出是正确的,请不要担心奇怪的代码执行顺序。
例:
#define AAA 1
#define BBB 2
int X::func(int i) {
bool b = (i == 5);
int v = (b ? 10 : 5);
std::cout << "before switch/case" << std::endl;
switch (i) {
case AAA:
std::cout << "AAA, before if block" << std::endl;
if (b && v > 4) {
v = v + 1;
std::cout << "within AAA if block" << std::endl;
return 0;
}
std::cout << "AAA, after if block" << std::endl;
break;
case BBB:
std::cout << "BBB, before if block" << std::endl;
if (!b || v > 40) {
v = v + 2;
b = false; // direct jump here from the switch for i = AAA
std::cout << "BBB, within if block" << std::endl;
return 0;
}
std::cout << "BBB, after if block" << std::endl;
break;
}
std::cout << "after switch/case" << std::endl;
return -1;
}
--编辑--
如果为 case 语句添加 {} 括号可能会有所帮助:
case AAA:{
break;
}
如果您将内容从案例移动到单独的功能中,这肯定会有所帮助。这不会改进代码,但调试器肯定能够遍历它们。
我已经从原始项目(项目)构建了一个"克隆"项目(project_test)。在预构建步骤中,我有一个复制所有源文件的 rsync(重点是不要复制自动工具的东西):
rsync -a --exclude=tests/* --exclude=perf/* --exclude=tools/* --include=*/ --include=*.[ch] --include=*.[ch]pp --exclude=* ${workspace_loc:/project}/ ${workspace_loc:/project_test}/ && cp ${workspace_loc:/project}/tests/one_with_main.cpp ${workspace_loc:/project_test}/tests/
它构建良好,调试符合预期。
另一种选择可能是rsync -a --delete
而不是rsync -a
。
- 检查是否至少设置了一点而不跳跃
- 如何使用训练的跳跃模型预测单词?
- 与其他输入相比,达到 65535 时的性能大幅跳跃
- TCS 模拟生活 2019 第 2 轮问题:跳跃游戏
- 瓦尔格林德有条件跳跃
- 是否有针对跳跃二进制搜索的直观解释
- 跳跃游戏中嵌套的循环问题
- 跳棋多跳跃计数算法
- Valgrind抱怨使用有条件跳跃,这些跳跃取决于非初始化的字节
- GCC 5.4.0的一次昂贵的跳跃
- 如何通过 zeromq 发送包含 \0 的序列化跳跃运动帧?
- C 计数跳跃范围末端
- 奇怪的循环跳跃C++
- 玩家跳跃的问题
- LLVM中直接跳跃的分支指令
- 在角色上跳跃功能
- 游戏跳跃逻辑
- 带有字符* 和 << 运算符的条件跳跃瓦尔格林德
- 助推::精神部分跳跃
- 无法在跳跃中为数组赋值