【问题标题】:How could this code behave as I saw?这段代码怎么能像我看到的那样表现?
【发布时间】:2011-06-09 18:20:29
【问题描述】:

我有一个 C++ 应用程序,它发生了一次无法重现的断言失败。这是一次失败的代码:

unsigned int test(std::vector<CAction> actionQueue) {
  unsigned int theLastCount = actionQueue.size() - 1;

  std::vector<CAction>::const_reverse_iterator rItr = actionQueue.rbegin();
  std::vector<CAction>::const_reverse_iterator rEndItr = actionQueue.rend();

  for (; rItr != rEndItr; ++rItr, --theLastCount) {
    const CAction &fileAction = *rItr;

    if (fileAction.test()) {
      continue;
    }
    return theLastCount;
  }

  assert(theLastCount == 0); // How could this fail?

  return theLastCount;
}

不知何故,循环完成后,theLastCount 不为零。

根据我对逻辑的阅读,这应该是不可能的,除非:

  1. 其他一些线程影响了 actionQueue(我认为这是不可能的)。
  2. 发生了一些短暂的内存损坏。

我在这里错过了什么愚蠢的东西,我的代码中是否有错误?请注意,在我看到这一点时,theLastCount 应该被初始化为 1,因为该向量有两个元素。

【问题讨论】:

  • NOT怎么会失败呢?请参阅 DeadMG 的回答。
  • @PigBen 如果内部返回被击中。
  • 但是这个值没有经过测试。不参加考试就不会失败。

标签: c++ puzzle fencepost


【解决方案1】:

如果队列为空怎么办?

theLastCount 将是 -1,然后... :-)

【讨论】:

    【解决方案2】:
    void test(std::vector<CAction> actionQueue) 
    {
      unsigned int theLastCount = actionQueue.size() - 1;
      /** Omitted code ***/
      {
        /** Omitted code ***/
        return theLastCount;
      }
      return theLastCount;
    }
    

    忘记您无法重现的错误。但这是一个严重的问题。返回类型是void,你却返回unsigned int!!怎么会?


    我想,你需要这样写:

    assert(theLastCount == -1);//correct assert!
    

    这是因为如果 test() 传递给所有元素,那么 theLastCount 应该变为 -1。由于没有剩余元素,并且 theLastCount 始终是有效的元素索引 if 有元素。否则它应该变成-1。

    注意:theLastCount 的类型从unsigned int 更改为int

    【讨论】:

    • 为这篇文章创建书面代码版本时出错,实际代码返回 unsigned int。
    • @William:好的。那我看看还有什么!
    【解决方案3】:

    在您将代码发布到此处之前,请编译并运行您的代码!首先,这段代码不能编译(我不会告诉你为什么——你可以问你的编译器)。其次,您的断言永远不会成功,因为 theLastCount 将始终为 (unsigned int)-1。

    【讨论】:

    • 代码可以编译,问题是这个帖子的简化。
    【解决方案4】:

    我相信如果 test() 对所有 fileActions 都通过了,theLastCount 将是 -1。考虑:

    theLastCount 从 actionQueue.size() -1 开始。对于 actionQueue 中的每个项目,您将其递减一次 - 也就是说,它现在是 actionQueue.size() - 1 - actionQueue.size() = -1。想想看。 theLastCount 保存当前迭代器的索引。但是当当前迭代器是rend时,那是数组开头之前的一个迭代器-即-1。

    编辑:哦,它没有签名。但是由于您只测试是否等于 0,因此积分溢出在这里并不重要。

    【讨论】:

    • 我现在需要弄清楚的问题是,为什么循环结束不能重现,其他地方只有一次出错了,它发现了这个错误,这是一个以前没有命中的栅栏,尽管有数千之前的调用。一个旧的错误发现另一个潜伏在代码中很长时间的错误的案例。
    【解决方案5】:

    如果你的actionQueue是空的,那么

    unsigned int theLastCount = actionQueue.size() - 1;
    

    theLastCount 设置为最大可能的无符号整数。内部循环永远不会执行,因为反向迭代器彼此相等(rbegin() == rend() 在空容器上),因此您将使用等于某个惊人数字的theLastCount 进行断言。

    【讨论】:

    • 好点,但是,在我的情况下,如果向量为空,则函数将永远不会被调用。
    • 不过,更一般地说,如果循环运行完成,您将始终拥有最大无符号值。您从 actionQueue.size() - 1 开始计数器,然后如果您从未在循环中点击 return 语句,则可能会将其递减 actionQueue.size() 次。
    猜你喜欢
    • 2019-05-30
    • 2017-08-15
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2012-10-12
    相关资源
    最近更新 更多