Освобождение памяти от карты.C ++ - PullRequest
3 голосов
/ 14 июня 2010
std::map<int, int> * mp = new std::map<int, int>;
for(int i = 0; i < 999999; i++){
  mp->insert(std::pair<int, int>(i, 999999-i )); 
}
p("created");
//mp->clear();     -     doesn't help either
delete mp;
p("freed");

Проблема в том, что «delete mp» ничего не делает. Для сравнения:

std::vector<int> * vc = new std::vector<int>;
for(int i = 0; i < 9999999; i++){
  vc->push_back(i); 
}
p("created");
delete vc;
p("freed");

освобождает память. Как освободить память от карты?
PS: p («строка») просто приостанавливает программу и ждет ввода.

Ответы [ 4 ]

9 голосов
/ 14 июня 2010

ОЗУ, используемая приложением, не является точным способом определить, была ли память семантически освобождена.

Освобожденная память - это память, которую вы можете использовать повторно.Иногда, однако, вы не наблюдаете эту освобожденную память непосредственно в том, что операционная система сообщает как память, используемая нашим приложением.

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

2 голосов
/ 14 июня 2010

Как отмечает Даниэль, ОЗУ, используемое приложением, не обязательно является индикатором утечки памяти. Что касается поведения, которое вы замечаете в отношении векторов, вектор гарантирует, что компоновка памяти является смежной, и, следовательно, когда вы создаете вектор размером 99999999, все элементы 99999999 размещаются в последовательности и представляют собой довольно значительный кусок памяти. Удаление этого, безусловно, повлияет на размер процесса. Карта ведет себя по-разному (согласно Википедии, она часто реализуется как самобалансирующееся двоичное дерево), поэтому я предполагаю, что ее удаление приводит к фрагментации в пространстве памяти процесса и, возможно, из-за того, что память процесса не падает немедленно. Лучший способ обнаружить утечки памяти - использовать такой инструмент, как valgrind, который четко покажет, что не так.

2 голосов
/ 14 июня 2010

На самом деле, если следующий код не течет:

{
  std::map<int, int> some_map;
}

Следующий код также не должен пропускать :

{
  std::map<int, int>* some_map = new std::map<int, int>();
  /* some instructions that do not throw or exit the function */
  delete some_map;
}

Это применимо к любому типу, который вы используете с new, если тип хорошо написан. И std::map, вероятно, очень хорошо написано.

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

1 голос
/ 14 июня 2010

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

#include <map>
#include <iostream>
#include <utility>

class Dtor{
        int counter;
    public:
        explicit Dtor(int c):counter(c) {std::cout << "Constructing counter: " << counter << std::endl; }
        Dtor(const Dtor& d):counter(d.counter) {std::cout << "Copy Constructing counter: " << counter << std::endl; }
        ~Dtor(){ std::cout << "Destroying counter: " << counter << std::endl; }
};

int main(){
    std::map<int, const Dtor&> * mp = new std::map<int, const Dtor&>;
    for (int i = 0; i < 10; ++i){
        mp -> insert(std::make_pair(i, Dtor(i)));
    }
   delete mp;
   return 0;
}

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

...