私たちのプロジェクトの 1 つでメモリ リンクを調査しているときに、奇妙な問題に遭遇しました。どういうわけか、オブジェクトに割り当てられたメモリ (オブジェクトへの shared_ptr のベクトル、以下を参照) は、親コンテナーがスコープ外になり、小さなオブジェクトを除いて使用できない場合に完全に回収されません。
最小限の例: プログラムの開始時に、1.5Gb の単一の連続ブロックを問題なく割り当てることができます。(いくつかの小さなオブジェクトを作成および破棄することによって) メモリをある程度使用した後、大きなブロックの割り当てを行うことができなくなります。
テストプログラム:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class BigClass
{
private:
double a[10000];
};
void TestMemory() {
cout<< "Performing TestMemory"<<endl;
vector<shared_ptr<BigClass>> list;
for (int i = 0; i<10000; i++) {
shared_ptr<BigClass> p(new BigClass());
list.push_back(p);
};
};
void TestBigBlock() {
cout<< "Performing TestBigBlock"<<endl;
char* bigBlock = new char [1024*1024*1536];
delete[] bigBlock;
}
int main() {
TestBigBlock();
TestMemory();
TestBigBlock();
}
また、shared_ptr の代わりに new/delete または malloc/free サイクルでプレーン ポインターを使用すると、問題が繰り返されます。
犯人は、TestMemory() の後、アプリケーションの仮想メモリが 827125760 のままであるようです (呼び出し回数に関係なく)。結果として、1.5 GB を保持するのに十分な大きさの空き VM 領域がありません。しかし、理由はわかりません。使用したメモリを確実に解放しているためです。OS呼び出しを最小限に抑えるためにCRTが行う「パフォーマンスの最適化」ですか?
環境は Windows 7 x64 + VS2012 + LAA なしの 32 ビット アプリです。