3

valgrind でコードをチェックしましたが、メモリ リークはありません。しかし、私は「トップ」を使用してメモリを表示します。「削除」が呼び出された後、295MBのメモリが必要です。
「pmap -x」を使用してメモリを確認します。ほとんどのメモリ コストは [anon] によるものです。

Address           Kbytes     RSS   Dirty Mode   Mapping
0000000001114000  301672  301588  301588 rw---    [ anon ]

メモリが解放された理由はわかりませんが、それでも 295MB かかります。理由を知っている人はいますか?

#include <map>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
void test8() {
  map<string, map<string,string>* > m;
  for (int i = 1; i < 10000; i++) {
    map<string, string>* p = new map<string, string>();
    for (int j = 1; j < 100; j++) {
      (*p)[string(j,'a')] = string(j,'a');
    }
    m[string(i,'a')] = p;
  }

  map<string, map<string,string>* >::iterator it;
  for (it = m.begin(); it != m.end(); it++) {
    it->second->clear();
    delete it->second;
  }
  m.clear();
  cout << "free done" << endl;
}
int main(int argc, char**argv) {
  test8();
  getchar();
}
4

3 に答える 3

1

使用しているツールは、オペレーティング システムからプロセスによって割り当てられたメモリを監視していますが、C++ プログラムで現在アクティブなメモリ割り当てのサイズは監視していません。

C++ コードでメモリを割り当てる場合、OS に出向いて追加を要求する必要がある場合があります。これにより、監視している値が増加します。

ただし、メモリを解放するときに、そのメモリを OS に戻す必要はありません。

そのため、C++ プログラムがメモリを解放したとしても、C++環境は、再度必要になった場合に備えてメモリを保持しています。

于 2015-09-02T02:54:48.730 に答える
1

これは OS 固有ですが、通常、プロセスがメモリを取得すると、それは保持されます。メモリを使用していない可能性がありますが、プロセスで (フリー プールで) 使用できます。

于 2015-09-02T02:54:49.883 に答える
1

キャッシング、キャッシング、キャッシング。そうそう、そして断片化。

メモリは異なるレイヤーを介して割り当てられます。アプリケーションがメモリを割り当てる場合、C/C++ ランタイムに要求します。C/C++ ランタイムは、独自のデータ構造で使用可能なメモリをチェックし、メモリがない場合は呼び出しを OS に転送します。C/C++ ランタイム (およびバージョン) によっては、C/C++ ランタイムのデータ構造が広範囲に及ぶ場合や、C/C++ ランタイムが呼び出しを常に OS に直接転送する場合があります。Microsoft Visual Studio (現時点では Linux を使用していません。申し訳ありません) については、次のことを知っています。

  • 古いバージョンでは、C/C++ ランタイムに非常に広範なメモリ データ構造がありました。
  • 新しいバージョンでは、呼び出しが常に OS (Windows ヒープ) に転送されるようです。

これは、メモリの割り当てを解除するときに、C/C++ ランタイムがメモリを保持することを決定する場合があることを意味します (メモリを再度割り当てることにした場合にメモリをより迅速に返すことができるなど、いくつかの理由で)。空きメモリが多い)。OS はまったく同じことを行う可能性があります。メモリを再度割り当てたい場合に備えてメモリを準備しておくか、すぐに割り当て解除としてマークします。

そうそう、断片化。通常、メモリはページ単位で分割されます。Intel x86 および amd64 では、1 ページは 4KB です。各ページには、次のような情報が含まれています。

  • 保護権 (読み取り専用、読み取り/書き込み、実行 (DEP、NoX ビットを参照)
  • その実際の場所 (物理メモリ、ページファイルへのページアウトなど)

アプリケーションが 256 バイトの 16 倍を割り当て、幸運にもこのすべてのメモリが 4KB の 1 ページ内に割り当てられているとします。これらの割り当てのうち 15 個を解放すると、16 番目の割り当てではメモリ ページが割り当てられたままになり、OS が割り当て解除のマークを付けなくなります。1.5GB を割り当ててから 1.4GB を解放し、それでも 1.5​​GB のメモリを (OS に応じて) 消費するアプリケーションを作成するのは非常に簡単です。

これは、すべてのメモリの割り当てを解除したとしても、すべてのメモリの割り当てを完全に解除したとしても、いくつかの内部 C/C++ ランタイム データ構造、またはいくつかのページが割り当てられたままになるサード パーティのデータ構造 (キャッシュなど) が存在する可能性があることを意味します。

于 2015-09-02T03:24:53.210 に答える