ページ 11

メモリの解放について

Posted: 2008年4月13日(日) 05:56
by ほにゃー
どうも、再び質問をさせてもらいます。
私はC++を使いシューティングゲームを作成しています。


そのシューティングゲームの敵や弾、爆風などはそれぞれのクラスを作り、
listを使い追加と削除をしております。
しかし、キチンとeraseを使い要素の削除をしているはずなのですが、
タスクマネージャーで確認するとゲームを起動している間はメモリの使用率は
徐々に上がっていき、下がることがありません。

InitGraph()などでメモリに読み込んだ画像や音楽を消去した場合は
画像や音楽の分だけメモリの使用率がさがるのですが、
それ以外の部分は使用したままです。

そのため、ゲームを続けているとメモリリークを起こしてしまいます。
どうしたらメモリの使用率の上昇を防ぐことができるでしょうか?

どなたかご教授お願いいたします。


使用コンパイラ
VC++2005ExpressEdition

Re:メモリの解放について

Posted: 2008年4月13日(日) 21:32
by Justy
>タスクマネージャーで確認するとゲームを起動している間はメモリの使用率は
>徐々に上がっていき、下がることがありません

 細かい説明は省略しますが、Windowsのタスクマネージャーのメモリ使用量では
アプリケーションのメモリリークを厳密に調べることは出来ません。

(ハンドルの解放漏れとかはタスクマネージャでもちゃんと把握できるのですが・・・)


>そのため、ゲームを続けているとメモリリークを起こしてしまいます

 ソースコードと実際に実行したときの挙動を見てみないと正確な判断はできませんが、
上記の情報だけですとリークが発生している、と断定出来る状態ではないようです。

 まずは本当にリークしているかどうかを調べることが重要です。
 MSVC環境とのことですので、

ttp://msdn2.microsoft.com/ja-jp/library/e5ewb1h3(VS.80).aspx
ttp://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/MemLeaks/

 この方法でも試してみてはどうでしょう?

 MSVCの CRTライブラリを使えばメモリの状態のスナップショットを取ったり、
その比較をしたりできますので、比較的簡単にリークの検出・特定ができる可能性があります。



>どうしたらメモリの使用率の上昇を防ぐことができるでしょうか?

 使用率の上昇を防ぎたいのであれば、とにかく無駄なメモリを使わない
こと以外にはありません。

 画面に描画していないデータ(画像とか)はメモリから削除するとか、
音声は全てを読み込まないでストリーミング再生にするとか。

Re:メモリの解放について

Posted: 2008年4月14日(月) 19:13
by ほにゃー
Justyさん、回答ありがとうございます。
CRTライブラリを使用しメモリの状態を調べてみたところ、
やはりメモリリークを起こしているようでした。

そしてその原因はlistのあるようでした。
erase()やclear()で要素を削除してみても完全に消えきらずに4分の一ほど残っているようでした。
以下はlistのメモリ解放の実験に使用したプログラムのソース(一部略)です。
_CrtMemState s1;
	_CrtMemCheckpoint( &s1 );

	list<C_test*> test;

	_CrtMemCheckpoint( &s1 );
	_CrtMemDumpStatistics( &s1 );

	for(a = 0; a<1000 ; a++)
		test.push_back(new C_test(5));

	_CrtMemCheckpoint( &s1 );
	_CrtMemDumpStatistics( &s1 );

	test.clear();

	_CrtMemCheckpoint( &s1 );
	_CrtMemDumpStatistics( &s1 );
結果はこのようになりました。(一部略)

12 bytes in 1 Normal Blocks.
Largest number used: 11423 bytes.
Total allocations: 26123 bytes.

16012 bytes in 2001 Normal Blocks.
Largest number used: 27216 bytes.
Total allocations: 42123 bytes.

4012 bytes in 1001 Normal Blocks.
Largest number used: 27216 bytes.
Total allocations: 42123 bytes.


listの要素を完全に削除するにはどうしたらよいのでしょうか?
ご教授お願いします。

Re:メモリの解放について

Posted: 2008年4月14日(月) 19:32
by GPGA
newしたオブジェクトをdeleteしていませんから、メモリリーク起こして当然です。
test.clear();の前に以下の文を入れてください。
list<C_test*>::iterator it = test.begin();
for (; it != test.end(); ++it) {
	delete *it;
}
 

Re:メモリの解放について

Posted: 2008年4月14日(月) 22:17
by Justy
 まずは GPGAさんの書かれている通りなのですが、

>[color=#d0d0ff" face="monospace] list<C_test*> [/color]
 ポインタである必要が本当にありますか?
 必要なら仕方ないですが、list<C_test>とできないかどうか検討してみて下さい。


 基本的にリストの削除の度に deleteしなければならないのは著しく面倒で、
バグの元になります。

 どうしてもポインタにしたいのであれば、リストの削除を行ったときに
自動的に deleteしてくれるようなコンテナの使用(或いは作成)をしてみてはどうでしょう。

Re:メモリの解放について

Posted: 2008年4月15日(火) 15:38
by ほにゃー
なるほど、deleteを呼びだすのを忘れていたからですね。
deleteを追加したらメモリリークは起こらなくなりました。
ありがとうございます。

list<C_test*>となっていたのは、
listのことを勉強したサイトで<>の中身をポインタにしていたからです。
今見てみると、ゲームで使うのならばポインタである必要はありませんでした。

これでようやくゲーム制作を進めることができます。
本当にありがとうございました。