Как заставить мою std :: map освободить используемую память? - PullRequest
11 голосов
/ 13 апреля 2010

Я использую std :: map и не могу освободить память для ОС. Похоже,

int main(){
  aMap m;

  while(keepGoing){
    while(fillUpMap){
       //populate m
    }
    doWhatIwantWithMap(m);
    m.clear();//doesnt free memory back to OS

    //flush some buffered values into map for next iteration
    flushIntoMap(m);
  }
}

Каждый (fillUpmap) выделяет около 1 гигабайта, поэтому я очень заинтересован в том, чтобы вернуть его в мою систему до того, как он съест всю мою память.

Я испытал то же самое с std :: vector, но там я мог заставить его освободиться, выполнив обмен с пустым std :: vector. Это не работает с картой.

Когда я использую valgrind, он говорит, что вся память освобождена, так что это не проблема с утечкой, поскольку все хорошо очищается после запуска.

редактирование:

Флеш должен появиться после сброса.

Ответы [ 6 ]

13 голосов
/ 13 апреля 2010

m.clear() освобождает память обратно в кучу, но реализации кучи обычно не освобождают ее обратно в ОС (даже когда это возможно, такие проблемы, как фрагментация, затрудняют это).

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

Карты не имеют понятия емкости и размера, как у векторов.

3 голосов
/ 13 апреля 2010

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

1 голос
/ 13 апреля 2010

Я сделал простой тест, когда я помещаю некоторые данные в std :: map и затем вызываю std :: map :: clear ().

typedef std::map<int, unit_t,std::less<int>,  
     my_allocator<std::pair<const int, unit_t>, 4 > > contaner_t;
contaner_t keys;
keys[1] = 10;
keys[2] = 20;
keys[3] = 30;
keys.clear();

это результат printf, вставленный в мой тест:

Allocator # 4, Memory consumption:      56     (allocated   :       56)
Allocator # 4, Memory consumption:     112     (allocated   :       56)
Allocator # 4, Memory consumption:     168     (allocated   :       56)
Allocator # 4, Memory consumption:     112     (deallocated :       56),
Allocator # 4, Memory consumption:      56     (deallocated :       56),
Allocator # 4, Memory consumption:       0     (deallocated :       56),

Я думаю, что вам, вероятно, следует также проверить свое поведение распределителя, но я думаю, что ваш стандартный std :: allocator фактически освобождает память, как вы ожидаете, но эта память не возвращается в ОС. Кстати, какую ОС вы используете?

Вопрос здесь в том, как вы измеряете can't seem to free the memory back to the OS. и как вы можете быть уверены, что I could force it to free by doing a swap with an empty std::vector. Вы действительно уверены, что выделенная память фактически возвращается к ОС?

1 голос
/ 13 апреля 2010

Если вы создадите карту в куче (через новую), ее удаление освободит всю используемую память.

0 голосов
/ 13 апреля 2010

Трюк с обменом?Я знаю, как вы делаете это с векторами и тому подобным, но я не делал этого раньше с картами.

0 голосов
/ 13 апреля 2010

Возможно, вы могли бы создать собственный распределитель или просто использовать Boost's пул библиотеку.

...