ошибка: освобождаемый указатель не был выделен

Я пытаюсь перегрузить оператор присваивания, чтобы сделать глубокую копию многоугольного объекта, программа компилируется, но ближе к концу я получаю сообщение об ошибке, которое я хочу устранить. Ниже приведен соответствующий код. Если вы считаете, что мне нужно добавить больше, просто оставьте комментарий. Предположим, что правильные #include и что оператор << перегружен для правильного вывода и т. Д.

Ошибка: malloc: * ошибка для объекта 0x1001c0: освобождаемый указатель не был выделен * установите точку останова в malloc_error_break для отладки.

//Polygon.h
// contains two classes PolygonNode and Polygon
class PolygonNode //Used to link points in a polygon so that they can be iterated through in order
{
public:
...
methods etc
...
private:
Point pt_; // the points in the polygon are made using the Point class
PolygonNode* link_ ; // pointer to the next point in the polygon
};

class Polygon // Connects points and forms a polygon { public: ... Polygon& operator= (Polygon ply); void Polygon::addPoint(const Point &p); // methods etc ... private: int numPoints_; bool closed_polygon_; PolygonNode* first_ ; // points to the first point of the polygon PolygonNode* last_ ; // points to the last point of the polygon };

//Polygon.cpp
...
PolygonNode::~PolygonNode()
{
    delete link_ ; // possible problem area
}

Polygon::~Polygon() { delete first_ ; // possible problem area last_ = NULL ; }

void Polygon::addPoint(const Point &p) { PolygonNode* ptr ; ptr = new PolygonNode(p) ; if( last_ != NULL ) last_->setLink(ptr) ; last_ = ptr ; if( first_ == NULL ) first_ = last_ ; numPoints_++ ; } Polygon& Polygon::operator= (const Polygon ply) { for (int i = 0; i < ply.numPoints()-1; i++) { addPoint(ply.getPoint(i)); } if (ply.isClosed()) { closePolygon(); } else { addPoint(ply.getPoint(ply.numPoints()-1)); } return this; } void Polygon::addPoint(const Point &p) { PolygonNode ptr ; ptr = new PolygonNode(p) ; if( last_ != NULL ) last_->setLink(ptr) ; // sets the last pointer to the new last point last_ = ptr ; if( first_ == NULL ) first_ = last_ ; numPoints_++ ; } ...

//main.cpp
Polygon ply;
...
        Point pt0(0,0);
        Point pt1(1,1);

    ply.addPoint(pt0);

    cout << "ply = " << ply << endl;
    Polygon newply;

    newply = ply; // use of the assignment operator

    cout << "Polygon newply = ply;" << endl;
    cout << "newply = " << newply << endl;
    cout << "ply = " << ply << endl;

    newply.addPoint(pt1);
    cout << "newply.addPoint(Point(0,0)); " << endl;

    cout << "newply = " << newply << endl;
    cout << "ply = " << ply << endl;

...

Я читал в другом месте, что это, возможно, связано с ошибкой в ​​OS 10.6 или Xcode 3.2, если есть обходной путь, может ли кто-нибудь дать мне подробные инструкции о том, как это сделать, у меня нет большого опыта работы с Xcode.

Отредактировано: добавлены части кода, в которых используется delete, обратите внимание, что он используется в деструкторах для Polygon и PolygonNode.

Отредактировано: добавлена ​​часть кода, в которой размещена ссылка_, setLink - это простой метод установки.


person Jordan    schedule 15.08.2010    source источник
comment
Эта ошибка, похоже, жалуется на то, как освобождается память, однако в настоящее время вы не показываете какой-либо код, который это делает. Любой код, использующий free или delete, вероятно, очень важен для этой ошибки.   -  person TheUndeadFish    schedule 15.08.2010
comment
@TheUndeadFish: я обновил вопрос, см. Edit внизу   -  person Jordan    schedule 15.08.2010
comment
Где вы разместили link_ переменную? эта часть кода отсутствует в вашем примере.   -  person Sadeq    schedule 15.08.2010
comment
@ PC2st: обновился, обратите внимание на метод addPoint   -  person Jordan    schedule 15.08.2010
comment
Вы реализовали конструкторы и инициализировали указатели нулевым значением? Сообщение об ошибке указывает на унифицированный указатель.   -  person Markus Kull    schedule 15.08.2010
comment
@Jordan: Вы продублировали функцию addPoint () ... там нет переменной link_, это last_! :)   -  person Sadeq    schedule 15.08.2010
comment
@Markus: указатели инициализируются значением NULL.   -  person Jordan    schedule 16.08.2010
comment
@ PC2st: Извините, если я не понял, что именно метод setLink () назначает атрибут link_ неявного параметра явному параметру.   -  person Jordan    schedule 16.08.2010


Ответы (3)


Я не вижу конструктора для класса PolygonNode. Указатель link_ инициализируется нулевым значением при создании? В противном случае проблема может заключаться в полученной ошибке. Вы должны убедиться, что указатели link_ в экземплярах PolygonNode инициализируются нулевым значением. Определите подходящие конструкторы.

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

Конструктор копирования, который автоматически синтезируется компилятором, просто скопирует указатели в классе Polygon.

Ваш оператор присваивания принимает аргумент по значению

Polygon& operator= (Polygon ply);

Это использует конструктор копирования. Если это автоматически синтезируемый, ply внутри оператора имеет указатели, указывающие на тот же список, которым владеет аргумент, переданный по значению оператору. ply ведет себя так, как будто он тоже владеет списком, и список уничтожается, когда ply выходит за пределы области видимости. Исходный аргумент остается с висячими указателями.

Вы должны определить правильный конструктор копирования.

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

person Maciej Hehl    schedule 15.08.2010
comment
link_ инициализируется значением NULL, хотя это было хорошей мыслью. - person Jordan; 16.08.2010
comment
@Jordan Так как насчет конструктора копирования? Если он не определен должным образом, некоторые объекты удаляются дважды. Конструктор копирования, вероятно, так же сложен, как оператор присваивания, может быть, немного меньше. Если вы хотите сначала протестировать оператор, перед конструктором копирования измените подпись оператора, чтобы передать аргумент по ссылке (const). Таким образом, конструктор копирования не будет использоваться. - person Maciej Hehl; 16.08.2010
comment
Я попытался реализовать конструктор копирования так же, как реализовал оператор присваивания (за исключением того, что я не return *this;), и это сработало. Спасибо за помощь - person Jordan; 16.08.2010

Я думаю, проблема в переменной link_, она не выделена в вашем примере и никогда не использовалась ...

person Sadeq    schedule 15.08.2010

Вы никогда не должны использовать необработанные указатели, кроме как в выделенном классе, как правило. Измените их на интеллектуальный указатель (в этом случае подойдет автоматический или общий доступ) и перестаньте освобождать собственную память -> проблема решена. Редактировать:

Более разумный вариант - просто использовать std :: list или std :: vector.

person Puppy    schedule 15.08.2010
comment
Я думаю, никогда не бывает слишком сильным. Достаточно нежного поощрения к контейнерам. - person Mark Essel; 06.06.2012
comment
Я думаю, что никогда, никогда ... обычно это очень сбивающая с толку рекомендация! - person OJFord; 31.01.2014