У меня есть проект Arduino, и я создал эту структуру:
struct Project {
boolean status;
String name;
struct Project* nextProject;
};
В моем приложении я анализирую некоторые данные и создаю Project
объекты. Чтобы они были в списке, есть указатель на nextProject
в каждом Project
объект ожидать последнего. Это код, где я добавляю новые проекты:
void RssParser::addProject(boolean tempProjectStatus, String tempData) {
if (!startProject) {
startProject = true;
firstProject.status = tempProjectStatus;
firstProject.name = tempData;
firstProject.nextProject = NULL;
ptrToLastProject = &firstProject;
} else {
ptrToLastProject->nextProject = new Project();
ptrToLastProject->nextProject->status = tempProjectStatus;
ptrToLastProject->nextProject->name = tempData;
ptrToLastProject->nextProject->nextProject = NULL;
ptrToLastProject = ptrToLastProject->nextProject;
}
}
firstProject
является частной переменной экземпляра и определяется в заголовочном файле следующим образом:
Project firstProject;
Так что, если там на самом деле не был добавлен проект, я использую firstProject
, чтобы добавить новый, если firstProject
установлен я использую nextProject
указатель.
Также у меня есть reset()
метод, который удаляет указатель на проекты:
void RssParser::reset() {
delete ptrToLastProject;
delete firstProject.nextProject;
startProject = false;
}
После каждого разбора я звоню reset()
проблема в том, что используемая память не освобождается. Если я закомментирую addProject
метод нет проблем с моей памятью. Кто-то может сказать мне, что может вызвать утечку памяти?
Прежде всего, вам не нужна переменная startProject
— просто инициализировать firstProject
указатель с NULL и затем напишите ваше условие следующим образом:
if (firstProject)
{
// There is a project, so append the new one.
}
else
{
// There is no project, so we need to create a new list.
}
Значение FALSE
определяется как 0, так же как NULL. Если firstProject
NULL выражение будет выглядеть if (FALSE)
и продолжить исполнение внутри else
-блок.
Так что теперь ваш reset
-Метод должен освободить память, выделенную для все проекты, а не только последний и второй, как ваш код.
delete ptrToLastProject; // Free last project
delete firstProject.nextProject; // Free the project following to the first one.
Проблемы здесь:
ptrToLastProject == firstProject.nextProject
? Второй delete
Утверждение освободит уже освобожденную память.firstProject
никогда не выпускаетсяЛучший способ освободить односвязный список — это что-то вроде этого:
Project* pProject = firstProject;
Project* pProjectToDelete;
while (pProject) // As long as the pointer points to something (see the first comment)
{
pProjectToDelete = pProject;
pProject = firstProject->nextProject;
delete pProjectToDelte;
}
В этой реализации вы «ходите» по списку, освобождая предшествующий элемент, если за ним следует следующий элемент. Если следующий элемент NULL
, последний элемент был освобожден и цикл прерывается.
И последнее, но не менее важное: вам нужно сбросить указатель на первый элемент (также называемый «якорь» в терминах структур данных):
firstProject = NULL;
это гарантирует, что addProject
не пытается добавить проект в NULL
,
Ваш reset
функция должна перебирать цепочку проектов, а не просто удалять первый и последний