очистка памяти, выделенной в стеке в c ++ - PullRequest
1 голос
/ 03 мая 2011

Я реализовывал шахматного бота на c ++, используя рекурсивные алгоритмы, и программа оценивает более миллиона узлов за ход.

Со временем занимаемая память достигает более 1 ГБ ОЗУ ...

Но мне действительно не нужны переменные, которые были объявлены ранее после того, как я закончил с перемещением ...

Итак, как мне вручную очистить память стека, чтобы избавиться от ранее объявленных переменных в стеке, как сборщик мусора в Java?

UPDATE

Я обнаружил, что в моем источнике есть эта строка:

Move * M = new Move(x1,y1,x2,y2);

pair <Move *, Piece *> pr (M,aPiece);

и это в функции выполнения перемещения, которая вызывается миллион раз в рекурсии ...

Мой вопрос: как бы вы очистили такую ​​переменную после завершения всей рекурсии, и мне больше не нужна эта переменная, но пока рекурсия делает свое дело, мне нужна эта переменная, чтобы она оставалась в памяти?

Ответы [ 5 ]

8 голосов
/ 03 мая 2011

Хранилище на основе стека восстанавливается, как только возвращается вызов функции, в которой оно находится.

Возможно ли, что вы использовали выделенную кучу память (т.е. вызывали new) в своей рекурсивной функции? В качестве альтернативы, если вы просто просматриваете диспетчер задач Windows или аналогичный, вы можете увидеть «пиковое» использование или некоторую задержку между освобождением памяти вашей программой и возвратом в пул памяти ОС.

Продолжение (после редактирования вопроса):

Непонятно, что вы делаете с pair<Move*, Piece*>, поэтому я не могу сказать, нужно ли удерживать объекты Move указателем или нет. Основными причинами их удержания с помощью указателя будет полиморфизм (здесь не используется, так как вы, кажется, не создаете объекты подкласса) и чтобы их время жизни не зависело от стека вызовов. Похоже, у тебя тоже нет этой причины. Так почему бы и нет:

std::pair<Move, Piece*> pr(Move(x1,y1,x2,y2), aPiece);
1 голос
/ 03 мая 2011

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

int recursive_function(int a, int b){
    int total;
    {  //new scope
         int temp[20];
         //do stuff using temp and total
    }  //temp goes out of scope, not taking up space on stack anymore
    total += recursive_function(a+total,b);
    {
         int temp[25];
         //do stuff with this other temp
    }
    total += recursive_function(a,b+total);

    return total;
}

РЕДАКТИРОВАТЬ:

В ответ на ваше обновление, если вы выделите память с помощьюnew, вам нужно освободить его с помощью delete, когда вы закончите с ним.В этом случае строка будет delete M;

void recursive_function(pair <Move *, Piece *> last_move){
    Move * M = new Move(x1,y1,x2,y2);
    pair <Move *, Piece *> pr (M,aPiece);
    recursive_function(pr);
    delete M;
}
0 голосов
/ 03 мая 2011

По поводу обновления: почему Move* и new Move? Move звучит как объект значения, который можно скопировать. То же самое Piece (но это менее точно - у вас могут быть уникальные экземпляры для каждый Piece).

0 голосов
/ 03 мая 2011

Я думаю, что гораздо более вероятно, что ваши объекты, расположенные "в стеке", не имеют к этому никакого отношения, и что на самом деле вы забываете delete то, что вы ранее new d.Возможно, этот Move объект?

0 голосов
/ 03 мая 2011

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

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