【问题标题】:Method not being called in switch statementswitch 语句中未调用方法
【发布时间】:2009-12-06 05:13:07
【问题描述】:

编辑:现在可以在调试器中完美运行,但正常运行时块根本不旋转..

我遇到了一个问题,我已经在调试器中运行了很多次并将其缩小到这个范围。

我的屏幕上有一块从中间落下并旋转的方块。块的图像明显变化取决于旋转,这是在 switch 语句中完成的。

switch ( m_CurrentRotation ) {
  case BossRotation_ZeroDegrees: {
    ApplySurface(
      m_BossRect.topLeftX,
      m_BossRect.topLeftY,
      BossFiveImage::p_ZeroDegrees,
      p_Buffer
    );
    break;
  }
  case BossRotation_NinetyDegrees: {
    ApplySurface(
      m_BossRect.topLeftX,
      m_BossRect.topLeftY,
      BossFiveImage::p_NinetyDegrees,
      p_Buffer
    );
    break;
  }
  case BossRotation_OneEightyDegrees: {
    ApplySurface(
      m_BossRect.topLeftX,
      m_BossRect.topLeftY,
      BossFiveImage::p_OneEightyDegrees,
      p_Buffer
    );
    break;
  }
  case BossRotation_TwoSeventyDegrees: {
    ApplySurface(
      m_BossRect.topLeftX,
      m_BossRect.topLeftY,
      BossFiveImage::p_TwoSeventyDegrees,
      p_Buffer
    );
    break;
  }
  default: {}
}

方块以零度进入,一旦进入中间,它就会开始旋转。我从调试中发现,在 switch 语句中,第一种情况的 ApplySurface 没有被调用(当我尝试进入它时,没有任何反应)。这会导致块在每次到达该旋转点时变为“空白”。

这里有一些奇怪的东西......

1) 如果 ApplySurface 函数没有被调用,那么为什么你会看到块开始下降(在它开始旋转之前)?

2) 在调试器中运行程序和正常运行会显示不同的结果。通常,它只是始终将块显示在其零度位置。调试器是它实际尝试旋转块的唯一时间。是否正在进行编译器优化以防止我的 switch 语句中出现可怕的错误?

【问题讨论】:

  • 当你附加一个调试器时,你改变了程序。至少,你改变了程序的时间。您应该查看线程和共享资源,以确保您没有遇到时间问题。此外,如果您在 switch 语句之前不提供代码,则很难调试正在发生的事情。如果没有附加代码,问题就变成了,“为什么我的代码没有进入 switch 语句的第一个 case?”答案就变成了“因为条件永远不会匹配那种情况。”
  • @atk 它确实输入了第一个 case 语句。它只是不调用该函数。 @米奇小麦谢谢。我会调查的。
  • Mitch 的评论让我想到了未初始化的指针。我去了我加载图像的地方,并注意到当我检查 null 时,我使用了 = 而不是 ==。我以前犯过这个错误,我认为是时候获得像 lint 这样的工具了。它现在在调试模式下完美运行,但在正常运行时仍然不旋转。
  • @person:这就是为什么应该使用 NULL==P 而不是 p==NULL

标签: c++ debugging switch-statement


【解决方案1】:

您的代码似乎不必要地冗长且重复。它应该被重构:

image = NULL;

switch ( m_CurrentRotation ) {
  case BossRotation_ZeroDegrees: {
    image = BossFiveImage::p_ZeroDegrees; break;
  }
  case BossRotation_NinetyDegrees: {
    image = BossFiveImage::p_NinetyDegrees; break;
  }
  case BossRotation_OneEightyDegrees: {
    image = BossFiveImage::p_OneEightyDegrees; break;
  }
  case BossRotation_TwoSeventyDegrees: {
    image = BossFiveImage::p_TwoSeventyDegrees; break;
  }
  default: {}
}

if (image) {
    ApplySurface(
      m_BossRect.topLeftX,
      m_BossRect.topLeftY,
      image,
      p_Buffer
    );
}

这个更简单的代码也应该更容易调试。 m_CurrentRotation 的类型和可能的值是什么?

【讨论】:

  • 不要使用 image == NULL 作为测试,您应该在切换之前将布尔标志设置为 true,并将默认大小写设置为 false。这更准确地反映了原始代码。但否则你是绝对正确的,代码应该以类似于你建议的方式重构。
  • @Omnifarious 我可以看到的一个反对意见是,假设 OP 正在调试并获得此功能。如果他测试 NULL,那么他会知道他尝试分配的图像之一是 NULL,因此他可能在某处输入了 = 而不是 == 的错误。使用布尔测试,他只知道没有一个案例被满足。因此,您可以测试案例内部的内容与测试是否满足任何案例。不太一样,我想我更喜欢第一个。替代方案:您可以同时测试两者。
  • 我实际上同意你的最后一句话 - 我认为测试两者(执行了非默认案例条款,并且图像不为空)可能是这里最好的解决方案。我演示的重构将这两件事结合到一个测试中,这将通过不显示图像来隐藏图像为空 - 也许程序终止会更好。无论哪种方式,重构都让事情变得更加清晰。
【解决方案2】:

Mark Byers 的回答非常棒 - 我首先会指出风格方面的问题之一:重复的代码几乎完全相同。 Mark 的回答确实有一个潜在的错误,因为他假设“image”的任何有效值都与 NULL 不同。由于不知道 BossFiveImage::p_ZeroDegrees 是什么想法,所以不知道检查 if (image) 是否也会跳过函数调用。

如果进行该更改没有帮助,那么我遇到了一些事情,这几乎肯定取决于编译器:

  1. 当代码在调试而不是在发布模式下编译时,未初始化的变量有时会归零(当然,我使用的所有 Microsoft c++ 编译器都会发生这种情况)。这可能会导致不同的行为。它们不需要是指针,它会影响所有变量。

  2. 也许您发生了一些异常处理,并且由于异常而没有发生函数调用 - 如果处理了异常,执行可能会继续正常,但如果您尝试传递给 ApplySurface 的任何内容() 抛出异常你可能会发现没有任何有用的事情发生。

【讨论】:

    【解决方案3】:

    很多时候调试 switch 语句会导致指令指针看起来像是在实际上与程序流程无关的行上。

    我敢打赌,你的 m_CurrentRotation 与 switch 语句中的任何内容都不匹配,这就是为什么没有调用任何内容的原因。你能设置一个监视,或者在默认子句中添加一些调试代码吗?

    【讨论】:

      猜你喜欢
      • 2014-01-17
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多