Linux glibc アロケータの動作がおかしいようです。うまくいけば、誰かがこれに光を当てることができます。私が持っているソースファイルは次のとおりです。
最初の.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;
}
秒.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.cpp $ g++ -o 秒 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 です。まず、なんらかの理由で割り当てをカーネルに解放しませんでした。
最初のプログラムはメモリをカーネルに解放しないのに、2 番目のプログラムは解放するのはなぜですか? 最初のプログラムはリンク リストを使用しており、リンク リストはおそらく、解放するデータと同じページにいくつかのノードを割り当てることを理解しています。ただし、これらのノードは解放する必要があります。これは、これらのノードをポップオフしてから、リンクされたリストをクリアするためです。これらのプログラムのいずれかを valgrind を介して実行すると、メモリ リークは発生しません。おそらく何が起こっているかというと、first.cpp ではメモリが断片化され、second.cpp では断片化されないということです。しかし、ページ上のすべてのメモリーが解放された場合、そのページが放棄されてカーネルに返されないのはなぜでしょうか? メモリが解放されてカーネルに戻るには何が必要ですか? メモリがカーネルに放棄されるように、first.cpp (char* をリストに追加し続ける) を変更するにはどうすればよいですか。