Распределитель Linux glibc, похоже, ведет себя странно. Надеюсь, кто-то может пролить свет на это. Вот исходный файл, который у меня есть:
first.cpp:
#include <unistd.h>
#include <stdlib.h>
#include <list>
#include <vector>
int main() {
std::list<char*> ptrs;
for(size_t i = 0; i < 50000; ++i) {
ptrs.push_back( new char[1024] );
}
for(size_t i = 0; i < 50000; ++i) {
delete[] ptrs.back();
ptrs.pop_back();
}
ptrs.clear();
sleep(100);
return 0;
}
second.cpp:
#include <unistd.h>
#include <stdlib.h>
#include <list>
int main() {
char** ptrs = new char*[50000];
for(size_t i = 0; i < 50000; ++i) {
ptrs[i] = new char[1024];
}
for(size_t i = 0; i < 50000; ++i) {
delete[] ptrs[i];
}
delete[] ptrs;
sleep(100);
return 0;
}
Я компилирую оба:
$ g++ -o first first.cpp $ g++ -o second second.cpp
Я запускаю сначала, и после его сна я вижу размер резидентной памяти:
Когда я компилирую first.cpp и запускаю его, я смотрю на память с помощью ps:
$ ./first&
$ ps aux | grep first
davidw 9393 1.3 0.3 64344 53016 pts/4 S 23:37 0:00 ./first
$ ./second&
$ ps aux | grep second
davidw 9404 1.0 0.0 12068 1024 pts/4 S 23:38 0:00 ./second
Обратите внимание на размер резидентной памяти. Сначала размер резидентной памяти составляет 53016k. во втором - 1024k. Сначала никогда не отпускал выделение обратно в ядро по той или иной причине.
Почему первая программа не освобождает память от ядра, а вторая программа? Я понимаю, что первая программа использует связанный список, и связанный список, вероятно, выделяет некоторые узлы на той же странице, что и данные, которые мы освобождаем. Однако эти узлы должны быть освобождены, поскольку мы выталкиваем эти узлы, а затем очищаем связанный список. Если вы запускаете любую из этих программ через valgrind, она возвращается без утечек памяти. Что, вероятно, происходит, так это то, что память фрагментируется в first.cpp, что не во втором. Cpp. Однако, если вся память на странице освобождена, как эта страница не будет возвращена обратно в ядро? Что нужно, чтобы память осталась обратно в ядро? Как я могу изменить first.cpp(продолжая помещать char * в список), чтобы память была оставлена в ядре.