L'allocatore di glibc di Linux sembra comportarsi in modo strano. Spero che qualcuno possa far luce su questo. Ecco il file di origine che ho:L'allocatore di Linux non rilascia piccoli pezzi di 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 entrambi:
$ g++ -o first first.cpp $ g++ -o second second.cpp
corro prima, e dopo aver dormito, vedo la dimensione della memoria del residente:
Quando compilo first.cpp ed eseguirlo, guardo 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
Avviso la dimensione della memoria residente. In primo luogo, la dimensione della memoria residente è 53016k. in secondo luogo, è 1024k. Per prima cosa non ho mai rilasciato le allocazioni al kernel per una ragione o per l'altra.
Perché il primo programma non rilascia la memoria nel kernel, ma il secondo programma funziona? Comprendo che il primo programma utilizza un elenco collegato e l'elenco collegato probabilmente alloca alcuni nodi nella stessa pagina dei dati che stiamo liberando. Tuttavia, questi nodi dovrebbero essere liberati, dato che stiamo spegnendo quei nodi, quindi cancellando l'elenco collegato. Se si esegue uno di questi programmi tramite valgrind, viene restituito senza perdite di memoria. Quello che probabilmente sta succedendo è che la memoria viene frammentata in first.cpp che non è in second.cpp. Tuttavia, se viene liberata tutta la memoria su una pagina, in che modo la pagina non viene restituita al kernel? Cosa ci vuole perché la memoria si ritrasferisca al kernel? Come posso modificare first.cpp (continuando a mettere il char * in una lista) in modo che la memoria venga abbandonata al kernel.
Usa ridursi per adattarsi, descritto [qui] (http://stackoverflow.com/questions/5834754/stddeque-does-not-release-memory-until-program-exits). In questo caso, fare 'std :: list() .swap (ptrs)'. –
jxh
Temo che ci sia qualcosa d'altro che non va qui ... Ecco il mio nuovo programma: int main() {{ std :: list PTR; per (size_t i = 0; i <50000; ++ i) { ptrs.push_back (nuovo carattere [1024]); } per (size_t i = 0; i <50000; ++ i) { delete [] ptrs.back(); ptrs.pop_back(); } ptrs.clear(); std :: list () .swap (ptrs); } sleep (100); ritorno 0; } ps esecuzione ha lo stesso risultato: davidw 9961 0.0 0.3 64344 53016 p.ti/4 S 00:31 00:00 ./first –
user1418199
perché questa etichettato C? –