Ошибка памяти C ++ при удалении - ошибка отладочного подтверждения - PullRequest
1 голос
/ 15 февраля 2012

Я пытаюсь добавить набор новых ModelImages к вектору и получаю сообщение об ошибке «Отладочное утверждение не выполнено», выражение: _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse).Это происходит при попытке удалить второй сгенерированный ModelImage.

std::vector<ModelImage> ModelImages;

for(int n=0;n<nParamSets;n++)
{
    ModelImage* mI = new ModelImage(MOD_WIDTH,MOD_HEIGHT);
    ModelImages.push_back(*mI);
    delete mI;
}

Функции конструктора и деструктора, а также функции копирования и обмена выполняются следующим образом:

ModelImage(int _width, int _height)
{
    width = _width;
    height = _height;
    nPixels = width*height;
    distance =  new float[nPixels];
    intensity = new float[nPixels];
    derivX =    new float[nPixels];
    derivY =    new float[nPixels];
    maxDistance = 0.0f;
    minDistance = 0.0f;
}

~ModelImage()
{
    delete [] derivX;
    delete [] derivY;
    delete [] distance;
    delete [] intensity;
}

ModelImage& operator=(ModelImage other)
{
    swap(*this, other);
    return *this;
} 

friend void swap(ModelImage& first, ModelImage& second)
{
    using std::swap;
    swap(first.derivX,second.derivX);
    swap(first.derivY,second.derivY);
    swap(first.distance,second.distance);
    swap(first.intensity,second.intensity);

    swap(first.nPixels,second.nPixels);
    swap(first.width,second.width);
    swap(first.height,second.height);
}

Непосредственно перед попыткойудалите второй ModelImage, глядя на вектор ModelImages показывает, что два ModelImages в векторе имеют одинаковые назначенные адреса памяти для массивов расстояния, интенсивности, DeriveX, производного.

Любая помощь приветствуется, спасибо.

Ответы [ 4 ]

2 голосов
/ 15 февраля 2012

Вероятно, это связано с тем, что у вас нет конструктора копирования.

Создайте конструктор копирования, который создает копии памяти, на которую ссылаются ваши указатели.

При использовании контейнеров std они обычно создают копии вашего объекта при вставке. Поскольку у вас нет конструктора копирования, все ваши указатели-члены в конечном итоге указывают на один и тот же адрес памяти, потому что он просто делает копию ваших данных для каждого члена. После уничтожения одной из временных копий (или когда вы вызываете delete для исходного объекта после вставки) в памяти вставленного объекта из-под него удаляется память.

1 голос
/ 15 февраля 2012

Мое первое предположение - у вас не определен конструктор копирования.Векторы 'push_back по умолчанию будут копировать конструкцию ModelImage, которая будет просто копировать указатели членов, но не перераспределять память, на которую они указывают.Однако эти ссылки исчезнут после удаления исходных объектов.

Подсказка: конструктор копирования выглядит примерно так:

ModelImage(const ModelImage& orig) {
  // appropriately reinitialize from orig
}

Не путать с присваиванием operator==

Почему вы все равно создаете эти ModelImage динамически (если вы их сразу бросаете)?И почему бы тебе не взять vector<float>(nPixels) вместо new float[nPixels]?

0 голосов
/ 15 февраля 2012

Я предполагаю, что у вас есть все массивы, определенные как указатели в классе.Копия по умолчанию копирует значения указателя, что означает, что при удалении указателя во внешней функции вы удаляете подчеркивающую память.

Всего пара предложений

-Используйте Vector вместо плавающего * std :: vector имеет конструкторы копирования и перемещения, определенные как полностью прочитанные

- Цикл не требуетсяиспользуйте свободное хранилище при любой семантике значений, и копирование полностью поддерживается и менее подвержено ошибкам.

 for(int n=0;n<nParamSets;n++)
 {       
     ModelImages.push_back( ModelImage(MOD_WIDTH,MOD_HEIGHT));
 }
0 голосов
/ 15 февраля 2012

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

distance
intensity
derivX
derivY

Если нет, они вам нужны.(см. Правило трех (программирование на C ++) для получения дополнительной информации).

Лучшей альтернативой было бы использование std::vector<double> для этих элементов данных.Таким образом, копирование, назначение и уничтожение будут выполняться автоматически.Вы все еще хотите построить их так, чтобы они содержали правильное количество элементов.

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