Ошибка сегментации, вызванная повторением pop_back() и push_back()

#c #segmentation-fault

Вопрос:

Когда я запускаю следующий код в Clion (IDE) с c 11. Я столкнулся с ошибкой сегментации. Но если я удалю оператор if, добавьте else перед pop_back, удалите push_back или удалите pop_back (делайте их отдельно). Ошибки не будет. Итак, почему может возникнуть ошибка сегментации и почему выполнение любого из вышеперечисленных действий устранит ошибку?

 #include "vector"
using namespace std;

int main() {
    vector<int> test;
    for(int i = 0; i < 10000; i  ){
        if(i % 2 == 0)
            test.push_back(i);
        test.pop_back();
    }
}
 

Редактировать: Некоторые люди говорят, что это потому, что pop_back из пустого вектора, но если я удалю push_back(), никаких проблем не будет (даже если я push_back некоторые элементы перед циклом).

Комментарии:

1. Вы push_back только для четных чисел, но вы pop_back для всех. Очевидно, что pop_backs больше, чем push_backs . Согласно std::vector::pop_back : вызов pop_back для пустого контейнера приводит к неопределенному поведению.

2. OT: это <vector> вместо "vector"

3. Пошаговое выполнение кода в отладчике быстро предупредит вас об этом дисбалансе нажатий и всплывающих окон.

4. Попробуйте поставить assert(test.size() > 0); перед test.pop_back() .

5. Неопределенное поведение @VagenteKing включает в себя отсутствие сообщения о какой-либо проблеме.

Ответ №1:

Вы выскакиваете из вектора, когда он пуст. Использование pop_back() из пустого вектора приводит к неопределенному поведению, что означает:

  • ваша программа может аварийно завершиться
  • ваша программа может печатать некоторые nonesens
  • ваша программа может продолжаться нормально
  • ваша программа может продолжаться нормально, но позже будет иметь какое-то другое странное, казалось бы, не связанное поведение
  • или какое-либо другое поведение

Рассмотрим этот код:

 #include <vector>
#include <iostream>

using namespace std;

int main() {
  vector<int> test;
    
  for (int i = 0; i < 10; i  ) {
    if (i % 2 == 0)
      test.push_back(i);

    if (test.empty())
      cout << "stack is empty" << endl;
    else
      test.pop_back();
  }
}
 

Комментарии:

1. Но если я удалю push_back() и у меня будет только pop_back() , ошибки сегментации не будет. Программа будет работать нормально и возвращать 0.

2. Неопределенное поведение @VagenteKing включает «по-видимому, работает нормально».

3. казалось бы, несвязанное поведение позже и даже раньше!