У меня есть рекурсивный метод в классе, который вычисляет несколько этапов (неважно, что это такое). Если он заметит, что вероятность успеха на сцене будет низкой, этап будет отложен, сохранив его в очереди, и программа будет искать более поздний этап позже. Он захватывает сцену, копирует данные для работы и удаляет сцену.
Программа работает нормально, но у меня проблема с памятью. Поскольку эта программа рандомизирована, может случиться так, что она задерживает до 10 миллионов этапов, что приводит к чему-то вроде использования памяти от 8 до 12 ГБ (или больше, но оно падает до того, как это произойдет). Похоже, что программа никогда не освобождает память для удаленной ступени, пока не дойдет до конца стека вызовов рекурсивной функции.
class StageWorker
{
private:
queue<Stage*> delayedStages;
void perform(Stage** start)
{
// [long value_from_stage = (**start).value; ]
delete *start;
// Do something here
// Delay a stage if necessary like this
this->delayedStages.push(new Stage(value));
// Do something more here
// Look for delayed stages like this
Stage* front = this->delayedStages.front();
this->delayedStages.pop();
this->perform(&front);
}
}
Я использую указатель на указатель, поскольку я думал, что память не освобождена, потому что есть указатель (фронт *), который указывает на сцену. Поэтому я использовал указатель, указывающий на указатель, и поэтому могу его удалить. Но, похоже, это не сработает. Если я смотрю использование памяти на мониторе производительности (в Windows), он выглядит примерно так:
Я отметил конец рекурсивных вызовов. Это также примерный сюжет. реальные данные, но в очень маленьком сценарии.
Любые идеи о том, как освободить память от более не используемых мудрецов до достижения стека вызовов?
редактировать
Я последовал советам и удалил указатели. Итак, теперь это выглядит так:
class StageWorker
{
private:
queue<Stage> delayedStages;
void perform(Stage& start)
{
// [long value_from_stage = start.value; ]
// Do something here
// Delay a stage if necessary like this
this->delayedStages.push(Stage(value));
// Do something more here
// Look for delayed stages like this
this->perform(this->delayedStages.front());
this->delayedStages.pop();
}
}
Но это ничего не меняло, использование памяти было таким же, как и раньше.
Как уже упоминалось, это проблема мониторинга. Есть ли лучший способ проверить точное использование памяти?
Просто, чтобы ответить на этот вопрос:
Матс Петерсон (спасибо большое) упомянул в комментариях, что это может быть проблема мониторинга использования памяти.
На самом деле это была проблема. Код, который я предоставил в редактировании (после замены указателей ссылками), освобождает пространство правильно, но он не возвращается ОС (в данном случае Windows). Так что с монитора видно, что пространство не освобождено.
Но затем я сделал несколько экспериментов и увидел, что освобожденная память повторно используется приложением, поэтому нет необходимости запрашивать ОС для большей памяти.
Так что показывает монитор, это максимальная используемая память, которая возвращает всю память, необходимую рекурсивную функцию, после завершения первого вызова этой функции.
std::queue<Stage*>
а неstd::queue<Stage>
? Т.е. почему вы не хотите, чтобы стандартная библиотека позаботилась об управлении памятью за вас? Если с ++ 11 не проблема, вы можете даже использоватьemplace
если вы заинтересованы в копировании Stages.So I used a pointer that point to the pointer, and so I can delete it.
: ссылка на указатель была бы намного понятнее.