Нужно ли удалять / освобождать динамически распределяемые данные (например, bytearray или std :: vector) внутри std :: deque, прежде чем я смогу вызвать pop_back? - PullRequest
0 голосов
/ 09 октября 2019

Насколько я понимаю, push_back () из std :: deque копирует данные, которые я вставил. Поэтому, когда я ссылаюсь на динамические данные (например, на динамический байт-массив или std :: vector), он копирует толькоссылка на это. Теперь я пытаюсь понять, нужно ли мне удалять / освобождать мои динамически распределяемые данные перед pop_back () из std :: deque? C ++ 11 дается. Надеюсь, кто-нибудь может мне помочь! Ниже приведены два моих сценария в качестве примеров кода:

Сценарий I:


  typedef struct mystruct{
    uint8_t* data; 
    //other fields may be here
  } mystruct_t;

  mystruct_t my;
  my.data = new uint8_t[3];
  my.data[0] = 'A';
  my.data[1] = 'B';
  my.data[2] = 'C';
  std::deque<mystruct_t> d;
  d.push_back(my);
  // ...
  // Need to delete/free data here, before d.pop_back()?
  d.pop_back();

Сценарий II:


  typedef struct mystruct{
    std::vector<uint8_t> data;
    // other fields may be here
  } mystruct_t;

  mystruct_t my;
  my.data.push_back('A');
  my.data.push_back('B');
  my.data.push_back('C');

  std::deque<mystruct_t> d;
  d.push_back(my);
  // ...
  // Need to delete/free data here, before d.pop_back()?
  d.pop_back();

1 Ответ

0 голосов
/ 10 октября 2019

ОК, потому что никто не отвечал, я пытаюсь ответить самому себе, учитывая новые выводы:

Я сделал несколько тестов во время выполнения кода, показанного выше, в бесконечном цикле, помещая 1 МБ данных в bytearray /вектор с / без освобождения и отслеживание поведения системной памяти во время работы.

Сценарий тестирования I:


struct mystruct{
  uint8_t* data; 
  //other fields may be here
};

int j = 0;
while(1){

  j++;

  mystruct my;
  my.data = new uint8_t[1000000]; // approx. 1 MB
  for(int i=0;i<=1000000;i++){
    my.data[i] = 'A';
  }      
  std::deque<mystruct> d;
  d.push_back(my);
  // TBD: Need to delete/free data here, before d.pop_back()?
  // delete[] d[0].data;
  d.pop_back();

  Log(LogLevel::kInfo) << "pushing and popping ... " << j;

}

Сценарий тестирования II:


  typedef struct mystruct{
    std::vector<uint8_t> data;
    // other fields may be here
  } mystruct_t;

  std::deque<mystruct_t> d;

    int j = 0;
    while(1){

      j++;

      mystruct my;      
      for(int i=0;i<=1000000;i++){  // approx. 1 MB
        my.data.push_back('A');
      }      
      std::deque<mystruct> d;
      d.push_back(my);

      // TBD: Need to delete/free data here, before d.pop_back()?      
      //  for(int i=0;i<=1000000;i++){  // approx. 1 MB
      //    d[0].data.pop_back();
      //  }  

      d.pop_back();

      Log(LogLevel::kInfo) << "pushing and popping ... " << j;

    }

Результаты:

  • Сценарий I значительно увеличивает объем используемой памяти и резко падает после запуска, когда байтовый массив не удален. Если байтовый массив удаляется в каждой итерации, все работает стабильно.

  • В сценарии II использование памяти остается стабильным, даже без выталкивания элементов из вектора <>. Так что, похоже, это сделано как-то внутренне. Сценарий II с выталкиванием каждого элемента из вектора до того, как выталкивать пятно, также был стабильным.

Дополнительные замечания: Сценарий II был намного медленнее, чем Сценарий I, особенно когда все элементы ввектор выталкивается каждый раз.

Был бы рад, если бы кто-то мог объяснить, почему память, выделяемая вектором, кажется освобожденной, когда выталкивающий элемент deque хоста выталкивается.

...