Удаление пользовательского массива вызывает ошибку кучи - PullRequest
1 голос
/ 31 октября 2010

TL; DR

Сбой Boost-Test-Framework без ошибок при прохождении всех тестов и утечке всей памяти.

Тест не пройден несколько раз с упомянутыми реализациями деструктора. Функция очистки также выдает ошибку кучи.

Что мы делаем не так с дтором?

TL; DR

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

Его задание является полным и полностью функциональным в соответствии с инструкцией 900-LOC Boost-Test нашего учителя. Единственная проблема - сбой (или ошибка кучи, так как не появляется сообщение об ошибке), когда тест завершается или вызывается внедренный dtor.

В его динамическом массиве используются три указателя: pFirst, pLast and pEnd, указывающий на первый элемент массива, на один после последнего элемента в массиве и указывающий на последний еще не выделенный элемент в массиве соответственно.

Его программа прошла, пока он не пытался удалить указатели. Это плохая идея, но эй, она позволила ему выполнить задание. На данный момент.

Мой друг несколько раз пытался реализовать деструктор, но они оба вызывают ошибки кучи и приводят к сбою тестовой среды.

// Teacher's recommended dtor.
Field::~Field()
{
    for(int i(0); i != this->size(); ++i)
        (pFirst+i)->~T();
    delete pFirst;
    pFirst = pLast = pEnd = NULL;
}

и

// My recommendation to friend.
Field::~Field()
{
    delete[] pFirst;
    pFirst = pLast = pEnd = NULL;
}

оба сбоя с одной и той же ошибкой кучи.

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

Типичная цепочка тестов выглядит так:

BOOST_AUTO_TEST_CASE( TEST_clear )
{
    Field f( 3, 4.0f );
    f.clear();  // Error here IF we use delete in the clear method.
    BOOST_CHECK( f.size()==0 );
    BOOST_CHECK( f.capacity()==4 ); 
} // Error here; during destruction IF we have implemented the dtor.

Метод clear выдает ту же ошибку, когда мы пытаемся заменить массив, поэтому у нас просто есть:

void Field::clear()
{
    size_t capa = capacity();
    T *temp =pFirst;
    pFirst = new T[capa];
    pLast = pFirst;
    pEnd = pFirst+capa;
}

Что мы делаем не так с dtor, понятно и вообще когда имеем дело с удалением указателей?

Ответы [ 2 ]

3 голосов
/ 31 октября 2010

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) указывает на повреждение кучи. Обычно это происходит, когда вы пишете после конца выделенной памяти. Я вижу следующую проблему в вашем коде: в Field::clear вы сохраняете указатель на выделенную память в pFirst и сразу перезаписываете его на pLast. Я думаю, вы должны изменить его на pLast = pFirst;.

Учитель, рекомендуемый доктором, не имеет смысла для меня. Если вы используете new[], а затем освобождаете delete[], не вызывайте каждый деструктор отдельно и используйте delete.

2 голосов
/ 31 октября 2010

Если pFirst указывает на первый элемент массива, то ваш «рекомендуемый учителем dtor» неверен. Вам нужно будет сказать delete[] pFirst, чтобы освободить массив.

Но есть много проблем, которые могут быть причиной этого, например, повреждение кучи, вызванное другой функцией. Попробуйте запустить это в программе проверки повреждения памяти, такой как Valgrind, чтобы проверить, не переполнен ли ваш буфер кучи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...