0

我已经分叉了一个 C++ 项目并在 switch 中添加了一些案例。然后它跳到下一个案例的中间。条件是 a int,案例值是#defined。由于代码很大,我在这里写了一些等效且简单的东西:

#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,代码执行会直接从BBB 案例内部跳转switch到内部。b = false;在真实的代码中,我有几十个案例,而且它发生在中间。如果我完全评论case BBB,它会在评论中跳到同一个地方!每个案例都以 a 结尾,break;并且内部没有变量声明。就像这里的变量 b 和 v 一样,它们是在 switch 语句之前声明的。

部分案例在一个#ifdef #endif区块中。出现问题的其他情况在此块中。条件为真,因此编译该块。不管怎样,我在抑制了这两个预编译器语句后测试了它,它是相同的。

如果我添加括号{}以完全包含这里的情况,我仍然有相同的结果:

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。

它看起来像一个编译器错误,但可能是什么原因?

4

2 回答 2

0

如果您通过调试器单步执行该函数,则调试器中的“当前突出显示的行”不一定对应于当前正在执行的行(涉及循环时、打开优化时、有很多宏时等)。

切换后将变量打印到 stdout/stderr 并查看它们的值是否正确。还将一些调试行打印到两个cases. 如果你得到的输出是正确的,不要再担心奇怪的代码执行顺序了。

例子:

#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;
}

如果您将案例中的内容转移到单独的功能中,这肯定会有所帮助。这不会改进代码,但调试器肯定能够遍历它们。

于 2013-09-13T13:33:42.977 回答
0

我已经从原始项目(项目)构建了一个“克隆”项目(project_test)。在预构建步骤中,我有一个复制所有源文件的 rsync(关键是不要复制 autotools 的东西):

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.

于 2013-09-15T09:49:32.960 回答