Как этот код может вести себя так, как я видел?

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

Я что-то упустил здесь, есть ли в моем коде ошибка? Обратите внимание, что в случае, когда я видел это, значение LastCount должно было быть инициализировано равным одному, поскольку вектор имел два элемента.

5 ответов

Решение

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

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

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

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

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

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

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

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,

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

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

Другие вопросы по тегам