Станд. C++:: вектор отказов удаления и сегментации указателей

В Rails 5

Student.
  find_or_initialize_by(:user_id => current_user.id).
  update(:department => 1)

(все отзывы взяты из ответа @Zorayr).

5
задан Sam 10 August 2014 в 14:29
поделиться

10 ответов

void Population::clearPool( std::vector <Chromosome*> & a )
{
   for ( int i = 0; i < a.size(); i++ ) {
      delete a[i];
   }
   a.clear();
}

Обратите внимание, что вектор передается по ссылке. В вашем коде используется копия вектора, что означает, что он не изменился в вызывающей программе. Поскольку вы удаляете указатели в копии, указатели в оригинале теперь недействительны - я подозреваю, что вы используете эти недопустимые указатели каким-то образом, не показанным в опубликованном вами коде.

Поскольку было опубликовано несколько шаблонных решений которые используют алгоритмы библиотеки C ++, вы также можете рассмотреть шаблонное решение, в котором нет:

template <class C> void FreeClear( C & cntr ) {
    for ( typename C::iterator it = cntr.begin(); 
              it != cntr.end(); ++it ) {
        delete * it;
    }
    cntr.clear();
}

Используя это, вы можете освободить любой контейнер динамически выделяемых объектов:

vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );
21
ответ дан 18 December 2019 в 05:27
поделиться

Немного измененная версия по сравнению с (@ 1800 ИНФОРМАЦИЯ).

  struct DeleteFromVector
    {
        template <class T>
        void operator() ( T* ptr) const
        {
            delete ptr;
        }
    };


std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
5
ответ дан 18 December 2019 в 05:27
поделиться

Я не знаю, почему у вас происходит сбой, но я предполагаю, что одна из возможностей заключается в том, что размер вектора не совпадает с размером, который вы передаете. Также я заметил, что вы повторяя от 0 до размера-2, разве вы не хотите пройти весь путь до конца?

Один из способов удалить все элементы в массиве с помощью идиоматического C ++ - это примерно так:

template<class T>
class deleter
{
  public:
    void operator()(const T* it) const
    {
      delete it;
    }
};

std::for_each(a.begin(), a.end(), deleter<Chromosome>());
3
ответ дан 18 December 2019 в 05:27
поделиться

У лямбда-выражения Boost уже есть функтор для удаления последовательностей указателей, кстати:

std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());
3
ответ дан 18 December 2019 в 05:27
поделиться

Я обнаружил проблему.

Она была в самом хорошо скрытом (не кем иным, как тупым старым мной) месте, какое только могло быть.

Как некоторые могли догадаться, это программа генетических алгоритмов. Это для учебника, который я делаю. Я выбирал точки кроссовера для хромосом случайным образом из функции колеса рулетки, которую я сделал. Ну ... внутри там было -1, чего там быть не должно. Это разрушило буквально все и в конечном итоге привело к ошибке сегментации.

Спасибо всем за вашу помощь, в этом посте я увидел несколько действительно хороших практик, которым я собираюсь следовать

1
ответ дан 18 December 2019 в 05:27
поделиться

Вы уверены, что каждый указатель в векторе указывает на другой объект? (т.е. два указателя не указывают на один и тот же объект, который вы пытаетесь удалить дважды.

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

2
ответ дан 18 December 2019 в 05:27
поделиться

Наиболее вероятная причина - это вызов delete дважды для одного и того же адреса. Это может произойти, если вы добавили один объект к вектору более одного раза. Чтобы обнаружить эту вставку некоторого оператора, который выведет адрес объекта, вы затем удалите .

printf( "will delete %d\n", (int)c );
delete c;
1
ответ дан 18 December 2019 в 05:27
поделиться

Я рекомендую использовать интеллектуальный указатель (например: auto_ptr) вместо необработанного указателя и просто использовать метод vector :: clear, который будет вызывать деструктор для каждого элемента

0
ответ дан 18 December 2019 в 05:27
поделиться
void Population::clearPool(std::vector<Chromosome*>& a)
{
    for(size_t i = 0; i < a.size(); i++) {
        delete a[i];
    }

    a.clear();
}
0
ответ дан 18 December 2019 в 05:27
поделиться

Похоже, что некоторые указатели в вашем коде не ссылаются на правильные объекты хромосомы. Это может произойти, если вы попытаетесь удалить некоторые объекты дважды в результате выполнения кода:

Population p;
vector<Chromosome*> chromosomes;
p.clearPool(chromosomes,chromosomes.size()); // You pass by value, so chromosomes is not changed
p.clearPool(chromosomes,chromosomes.size()); // Delete already deleted objects second time

Вы можете найти полезный ptr_vector в Библиотеке контейнера указателя повышения , чтобы избежать подобных ошибок

0
ответ дан 18 December 2019 в 05:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: