2014-02-21 3 views
0

При тестировании моего кода я постоянно получаю ошибки в отношении использования delete в качестве состояний тестового объекта моего класса, которые вызывают удаление из массива, выделенного с помощью нового []. Я удаляю в своих ~ IntVector и две функции расширения с функциями расширения, расширяющими емкость при перераспределении памяти для динамически распределенного массива.Неправильное выделение памяти?

Как правильно использовать удаление, чтобы предотвратить утечку памяти и устранить эту ошибку?

основной файл

#include "IntVector.h" 
#include <iostream> 
#include <vector> 
using namespace std; 


IntVector::~IntVector(){ 
    delete[] data; 
} 

void IntVector::expand(){ 
    cap = cap * 2; 
    int *data2 = data; 
    data = new int[cap]; 
    data = data2; 
    delete data2; 
    delete[] data2; 
} 

void IntVector::expand(unsigned amount){ 
    cap = amount; 
    int *data2 = data; 
    data = new int[cap]; 
    data = data2; 
    delete data2; 
    delete[] data2; 
} 

Заголовок

#ifndef INTVECTOR_H 
#define INTVECTOR_H 

using namespace std; 
class IntVector{ 
private: 
    unsigned sz; 
    unsigned cap; 
    int *data; 
private: 
    void expand(); 
    void expand(unsigned amount); 
}; 

#endif 
+0

Мой деструктор ~ IntVector. – user3314899

+0

Вы отправили много кода, очень сложно пропустить такую ​​небольшую функцию во всей этой стене кода. Вы можете прочитать [контрольный список вопросов переполнения стека] (http://meta.stackexchange.com/questions/156810/stack-overflow-question-checklist). Вы также можете узнать, что такое [SSCCE] (http://sscce.org/). –

+0

@ user3314899 - Сразу же программа 2-строчной основной() может сделать ваш класс падающим на его лице: 'int main() {IntVector a (10); IntVector b = a;} ' - это все, что вам нужно - у вас есть ошибка с двойным удалением в конце main(). Если я добавлю еще две строки, я могу воспроизвести утечку памяти. Прочитайте правило трех, так как другие предложили преодолеть эту ошибку. – PaulMcKenzie

ответ

3

При распределении new[] вы должны использовать delete[]. Ваша функция expand использует простой delete. Он также содержит некоторые другие ошибки (переназначение указателей, двойное удаление и т. Д.).

И где ваш экземпляр-конструктор? Оператор копирования-присваивания? Вы можете прочитать о the rule of three.

+0

Таким образом, это будет удалить [] данные вместо delete [] data2? – user3314899

+0

@ user3314899 Нет, по крайней мере, не для начала. Сначала вам нужно выделить новые данные, затем вам нужно скопировать старые данные в новые данные, тогда вам нужно освободить старые данные, и, наконец, вам нужно переназначить старый указатель данных, чтобы указать на новые данные. –

2

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

Если вы что-то вроде

IntVector x(IntVector(10)); 

вы будете слева с оборванным указателем в x, потому что оригинал ДЭ-выделяются, когда временный IntVector(10) выходит из области видимости.

0

В дополнение к правилу нарушения там, вы также пытаются удалить переменные дважды в ваших expand функций:

void IntVector::expand() 
{ 
    cap = cap * 2; 
    int *data2 = data; 
    data = new int[cap]; 
    data = data2; 
    delete data2; // this should not be here! 
    delete[] data2; // this will be a problem now! 
} 

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

Оба ваших расширяющих функции должен выглядеть как:

// copy-swap 
void IntVector::expand() 
{ 
    IntVector tmp; 
    tmp.reserve(cap * 2); 
    tmp.resize(sz); 
    std::copy(data, data + sz, tmp.data); 
    std::swap(*this, tmp); 
} 

или

// raw implementation 
void IntVector::expand() 
{ 
    unsigned int newCap = cap * 2; 
    int* newData = new int[newCap]; 
    std::copy(data, data + sz, newData); 
    delete [] data; 
    data = newData; 
    cap = newCap; 
} 

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

+0

При прямом использовании delete [] тестовая жгутовая связь срабатывает для меня. Я полагаю, что это было бы проблемой при назначении массиву? – user3314899

+0

@ user3314899 Вам нужно будет показать код, чтобы объяснить, о чем вы говорите. –

+0

void IntVector :: expand (неподписанное количество) { колпачок = количество; int * data2 = new int [cap]; data2 = данные; удалить [] данные; * данные = * данные2; } – user3314899

Смежные вопросы