RSS の測定は、計算方法が非常に複雑であるため、メモリ リークを検索するための正確な方法ではありません。valgrind
またはに組み込まれているような特別なメモリデバッガがありglibc
、メモリがリークしているかどうかを知ることができます。glibc
が2 つのまったく異なるメカニズムを使用してメモリを動的に割り当てることも理解する必要があります。
mmap(2)
大規模な割り当ての場合、システム コールを使用してプライベートな匿名メモリ マップを実行します。この方法では、システム ページ サイズの倍数 (ほとんどの最新のアーキテクチャでは 4 KiB) のサイズのブロックのみを割り当てることができるため、小さな割り当てには適していません。あまりにも多くのメモリが浪費されるような大規模な割り当てには適していません。たとえば、17 KiB のブロックを割り当てたい場合は、20 KiB (4 KiB の 5 倍) を割り当てる必要があり、メモリの 15% が割り当てられます。無駄。
より小さい割り当ての場合、システムが提供するヒープが使用されます。システム ブレークと呼ばれるものがあり、プロセスのデータ セグメントが終了します。これは、brk(2)
システム コール up で移動してより多くのメモリを割り当て、down で解放することができます。glibc
プロセスごとに 1 つのヒープ領域しかなく、OS はそれを 1 つのブロックとして扱うため、このブロックをさらに小さな割り当てに分割できる特別なヒープ マネージャーが組み込まれています。
C++new
演算子は、メモリ割り当てを実行するためにmalloc(3)
fromを呼び出します。割り当てられるメモリ ブロックのサイズに応じて、上記の 2 つのメモリ割り当てメカニズムのいずれかを呼び出します。C++演算子の呼び出しfrom which は、 の割り当て解除に相当します。メモリ ブロックの割り当てが解除された後に何が起こるかは、最初にどのように割り当てられたかによって大きく異なります。glibc
malloc(3)
delete
free(3)
glibc
malloc(3)
mmap(2)
メカニズムを使用して割り当てられたメモリは、 でマップを解除することによって割り当て解除されますmunmap(2)
。これにより、プロセスの仮想アドレス空間からメモリ マッピングが削除され、割り当てをサポートするために使用された物理メモリ ページが解放されます。
ヒープに割り当てられたメモリの場合、事態はさらに複雑になり、それを管理するために使用されるアルゴリズムに大きく依存します。解放されるブロックがヒープの最後ではなく、別の場所にある場合は、上位メモリ アドレスに他の割り当てがあるため、ヒープ サイズを減らすことはできません。これは、いわゆるヒープの断片化が現れる多くの形態の 1 つにすぎません。使用済みメモリの減少が見られないもう 1 つの理由として考えられるのは、ヒープ マネージャーが、将来の割り当ての可能性を見込んでブレークの位置を戻すことを決定する可能性があり、呼び出しbrk(2)
が高価な操作になることです。