Как этот код может вести себя так, как я видел? - PullRequest
3 голосов
/ 15 января 2011

У меня есть приложение 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 должен был быть инициализирован как один, так как вектор имел два элемента.

Ответы [ 5 ]

5 голосов
/ 15 января 2011

Я считаю, что если test () пройден для всех fileActions, theLastCount будет равен -1.Обратите внимание:

theLastCount начинается с actionQueue.size () -1.Вы уменьшаете его один раз для каждого элемента в actionQueue, то есть теперь это actionQueue.size () - 1 - actionQueue.size () = -1.Думаю об этом.theLastCount хранит индекс текущего итератора.Но когда текущий итератор разрисован, то это один итератор перед началом массива, который равен -1.

Редактировать: О, это без знака.Но поскольку вы проверяете только равенство нулю, то здесь переполнение не имеет большого значения.

2 голосов
/ 15 января 2011

Если ваше actionQueue пусто, то

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

установит theLastCount в максимально возможное целое число без знака. Внутренний цикл никогда не будет выполнен, потому что обратные итераторы равны друг другу (rbegin() == rend() в пустых контейнерах), и поэтому вы получите утверждение с theLastCount, равным некоторому поразительно огромному числу.

1 голос
/ 15 января 2011

Пожалуйста, скомпилируйте и запустите ваш код, прежде чем размещать его здесь!Во-первых, этот код не компилируется (я не говорю вам, почему - вы можете спросить свой компилятор).Во-вторых, ваше утверждение никогда не будет успешным, потому что theLastCount всегда будет (без знака int) -1.

1 голос
/ 15 января 2011
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 всегда является допустимым индексом элемента , если элемент есть.В противном случае оно должно стать -1.

ПРИМЕЧАНИЕ: Измените тип theLastCount с unsigned int на int.

0 голосов
/ 15 января 2011

Что если очередь пуста?

theLastCount будет -1, а затем ...: -)

...