メモリ開放(解消編)@シューティング

先日PGレビューしていただきました。
メモリの確保について最低限の構成で動作させてみてどこが開放されていないのか限定していく とアドバイスをもらったので、やっていきたいと思います。


検証

  • 同じ動作(画面遷移やファイルのロード)を10回ほど行う
  • 動作前と上の動作後で確保メモリ量を確認


とりあえず、画面遷移機能以外無効にして、検証しました。→メモリ使用量・仮想メモリ共に開放されている
ゲーム画面のユニットデータ領域のみ有効→同上
ファイルロード用領域も有効→若干(4kほど)リークしていたので、ファイルロード領域確認して修正。(realloc1回実行されて開放していなかった) その後、開放確認
SDL_Serface系を有効(画像ファイルは読み込んでいない)→開放確認
メモリ初期化(memset)系有効→開放確認
画像ファイルロード有効→開放確認

透過色設定有効→メモリリーク発生→SDL_DisplayFormat関数を実行するとメモリが開放されない


説明を読みましたが8割ほど意味がわからない単語だったので、とりあえず記載。。。


SDL_DisplayFormat 関数の概要〜
この関数はサーフェスを引数に取り、表示サーフェス上への高速 blit に適するように、ビデオフレームバッファピクセルフォーマットと色の新しいサーフェスにコピーします。その際 SDL_ConvertSurface を呼び出します。

ハードウェアによるカラーキーやαの blit 転送のアクセラレーションの利点を得たい場合は、この関数を呼ぶ前にカラーキーとα値をセットしておくべきです。

αチャンネルが欲しいならば SDL_DisplayFormatAlpha を見て下さい。




(調査中)


・・・・・・と、とりあえず、"高速blit"と転送方法があって、"ビデオフレームバッファ"という領域と、そこに書かれているデータのフォーマットが"ピクセルフォーマット"というところまでは調べました。そこがゴミになっているんだろうか。。。
フレームバッファ調べてたらインターレース方式とプログレッシブ方式とか出てきました。
そこまで把握しないといけないのかぁ。
ピクセルフォーマットのところでRGBじゃないフォーマットを初めて見ました。
そして、新しいサーフェスを生成して、コピーする時に、SDL_ConvertSurfaceを呼び出している。とのことです。

SDL_ConvertSurface 関数の概要〜
指定されたフォーマットの新しいサーフェスを生成し、与えられたサーフェスをコピー・写像します。この関数が失敗すると、NULL を返します。


お?生成?新しく領域を作っているのかな。もしかして、SDL_ConvertSurface関数を実行したら元ポインタから始まるサーフェス領域は開放されないため、Freeしないといけない仕様?

というわけで、まずサーフェスのポインタを出力

SDL_DisplayFormat: Src=9775104 -> Dst=9780944

新たに割り当てられて帰ってきていました。

次に、SDL_SurfaceをFreeしてみました。

SDL_DisplayFormat: Src=9775104 -> Dst=9780944
Free_SDL_Surface : = 9775104


結果、メモリリークが解消された!
おおおおおおおおお。きたあああああ
き☆た☆こ☆れ!


画面遷移を10回したときのメモリ使用量は以下のとおり!
↓Freeしないバージョン

↓Freeしたバージョン

劇的です。もう、画面遷移を何回しても増えません。

しかし、長かった・・・これで心機一転してコードが組めます。





と思い、順次実装を適用していくと、変な表示に。。。

黄色で囲ったところ。敵が弾になってたり、弾がロックオンカーソルになってたり。。。
えええええええええ!?
・・・ああ、そうか、コマとして登録した後に透過色(SDL_ConvertSurface関数)設定しているから参照先が変わってるんだ。→修正。

よし、元に戻ったし、メモリリークも解消できたっ!やったあああ