Указатели на объекты в области действия функции - PullRequest
2 голосов
/ 20 октября 2010

Когда вы создаете несколько указателей внутри области действия функции, что происходит, когда функция выходит из области видимости?Они уничтожены или я должен вызвать удаление их в какой-то момент?

void XMLDocument::AddNode(XMLNode& node)
{
    std::string val = node.GetNodeName();
    TiXmlElement* el = new TiXmlElement(val.c_str());  // What about this object ptr?
    TiXmlText * txt = new TiXmlText(node.GetNodeValue().c_str());  // And this one?
    el->LinkEndChild(txt);
    document.LinkEndChild(el);
}

Ответы [ 3 ]

6 голосов
/ 20 октября 2010

Обычно вам нужно вызывать delete для обоих указателей, чтобы избежать утечек памяти. Но в вашем случае, похоже, что вы помещаете этот указатель в document объект (я предполагаю, что document хранит указатель сам и не создает копию указанного возразить сам). Поэтому, если вы вызовете delete здесь, указатель, который вы дали объекту document, будет недействительным. Поэтому, если объект document вступает во владение удалением памяти, выделенной для этой функции, вам не следует вызывать delete здесь, иначе, если он создает копию объекта, который вы передали, вам нужно delete здесь , Использование умного указателя будет весьма полезно в подобных сценариях. Посмотрите boost :: shared_ptr для получения более подробной информации.

1 голос
/ 20 октября 2010

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

То, что происходит после выхода из функции, зависит от контракта на использование памяти, который подразумевается путем передачи указателя в LinkEndChild.У вас все еще остается память после этого или она очищается, когда очищается новый родитель (в данном случае document, который обращается к памяти напрямую для el, и через el для txt)?Если первое, то вы правы, не delete это.Если последнее, то в какой-то момент вам нужно его почистить, предположительно после того, как document (глобальный? Член класса?) Закончен с.

Еще один нюанс заключается в том, что такое контракт на строительство TiXmlElement и TiXmlText - копируют ли они входную C-строку или используют их по ссылке?

Я бы догадался, чтоЭто документ XmlDocument, чтобы очистить всю память, связанную с документом.Хотя это немного грязно.Проверьте деструктор XmlDocument::~XlmDocument, посмотрите, просматривает ли список детей, чистящих их (рекурсивно).

РЕДАКТИРОВАТЬ: Это похоже на TinyXML, в этом случае он должен очистить всю память, которую вы даете емуразрушение.Для обсуждения см. Здесь: http://www.gamedev.net/community/forums/topic.asp?topic_id=518023

Семантика TinyXML явно подразумевает, что (а) он владеет деревом документов и (б) вы передаете в узлах, которые вы выделяете.Я не вижу веских аргументов в пользу того, чтобы он не просто использовал оператор удаления для всего, что связано с ним.

РЕДАКТИРОВАТЬ: Фактически, учитывая, что TinyXML (или, по крайней мере, копия, которую я здесь имею) явно имеет while ( node ) { temp = node; node = node->next; delete temp; } вдеструктор TiXMLNode, я предполагаю, что это просто ошибка в оболочке TinyXML ++.

См. также предыдущий вопрос переполнения стека об управлении памятью TinyXml здесь .

Документация для LinkEndChild гласит:

ПРИМЕЧАНИЕ: добавляемый узел передается по указателю и отныне будет принадлежать (и удаляться) tinyXml.Этот метод эффективен и позволяет избежать лишней копии, но его следует использовать с осторожностью, поскольку он использует модель памяти, отличную от других функций вставки.

1 голос
/ 20 октября 2010

Когда вы используете new, память из кучи выделяется, а объекты, локально объявленные в функции, выделяются в стеке.
Объекты, выделенные стеку, перестают существовать после вызова метода.
В вашем случае TiXmlElement* el - это указатель, выделенный в стеке, который ссылается на память в куче. После выхода из функции указатель el перестанет существовать (поскольку он был в стеке), но память, на которую он ссылался, все еще существует (находилась в куче). Поэтому, если эта память не «освобождена», она считается «утекшей»

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