El asignador glibc de Linux parece comportarse de manera extraña. Con suerte, alguien puede arrojar algo de luz sobre esto. Aquí está el código fuente que tengo:El asignador de Linux no libera trozos pequeños de memoria
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;
}
Compilo tanto:
$ g++ -o first first.cpp $ g++ -o second second.cpp
corro en primer lugar, y después de que está durmiendo, veo el tamaño de la memoria residente:
Cuando puedo compilar first.cpp, y ejecutarlo, miro memoria con 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
Aviso del tamaño de la memoria residente. En primer lugar, el tamaño de la memoria residente es 53016k. en segundo lugar, es 1024k. Primero nunca lanzó las asignaciones al kernel por alguna razón u otra.
¿Por qué el primer programa no renuncia a la memoria del kernel, pero el segundo programa sí? Entiendo que el primer programa utiliza una lista vinculada y que la lista vinculada probablemente asigna algunos nodos en la misma página que los datos que estamos liberando. Sin embargo, esos nodos deberían liberarse, ya que estamos eliminando esos nodos y luego borrando la lista vinculada. Si ejecuta cualquiera de estos programas a través de valgrind, regresa sin pérdidas de memoria. Lo que probablemente está sucediendo es que la memoria se fragmenta en first.cpp que no está en second.cpp. Sin embargo, si se libera toda la memoria de una página, ¿cómo no se devuelve esa página al kernel? ¿Qué se necesita para que la memoria sea devuelta al kernel? ¿Cómo puedo modificar first.cpp (continuar colocando los caracteres * en una lista) para que la memoria se renuncie al kernel?
Uso encoge para caber, describe [aquí] (http://stackoverflow.com/questions/5834754/stddeque-does-not-release-memory-until-program-exits). En este caso, haga 'std :: list() .swap (ptrs)'. –
jxh
Me temo que no es otra cosa fuera de lugar aquí ... Aquí está mi nuevo programa: int main() {{ std :: lista PAD; para (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(); std :: list () .swap (ptrs); } sueño (100); return 0; } ps ejecución tiene el mismo resultado: davidw 9961 0,0 0,3 64344 53016 pts/4 S doce y treinta y uno 0:00 ./first –
user1418199
por qué se esta etiquetada C? –