メモリリークについて

解決


やましん  2010-12-10 21:08:14  No: 39695

http://blog.livedoor.jp/junki560/archives/21305807.html
上記にあるソースを使って、連続して画像ファイルをカウントするプログラムを組みたいのですが、
連続すると、どんどんメモリを食い始めます。

type
PColorCount = ^TColorCount;
TColorCount = record
  ColorData: integer;
  Count: integer;
end;
      ・
      ・
      ・
      ・
if (ls.Count < nnum) or (PColorCount(ls[nnum-1])^.Count < count) then
        begin
          New(pcc);
          pcc^.ColorData := integer(tl[i-1]);
          pcc^.Count := count;
          ls.Add(pcc);
          if ls.Count = nnum+1 then
          begin
            Dispose(PColorCount(ls[nnum]));
            ls.Delete(nnum);
          end;

このあたりで、New(pcc);で確保されたメモリを開放されてないのではないかと思うのですが、どうにも解決できません。
どなたかお解かりになる方いらっしゃいませんか?


tor  2010-12-10 22:09:05  No: 39696

Disposeに与えるポインタは正しい型の変数でなくてはいけません。
× Dispose(PColorCount(ls[nnum]));
○ var pcc: PColorCount; pcc := PColorCount(ls[nnum]); Dispose(pcc);

lsをClearしたりする際にも同様の注意が必要です。

そもそも、いったん追加してから削除するよりは、最初から「数が上限だったら追加しない」とした方が話が簡単だと思いますが……
1行目のorをandに変えたら解決したりしませんか?


ならしん  2010-12-11 01:05:48  No: 39697

>やましんさん
TListSortedが初期状態で重複を許さない設定になっているため、
ls.Addの戻り値が-1の場合、重複で追加されないpccがどんどん溜まるのが原因だと思われます。
ですので、
ls.Add(pcc);
を、
if ls.Add(pcc) = -1 then
  Dispose(pcc);
と書き換えることでリークが解消できるはずです。

>torさん
>Disposeに与えるポインタは正しい型の変数でなくてはいけません。
>× Dispose(PColorCount(ls[nnum]));
>○ var pcc: PColorCount; pcc := PColorCount(ls[nnum]); Dispose(pcc);

これは間違いです。
Disposeに与えるポインタはキャストで問題ありません。
Disposeの実装は動的な型(stringなど)が含まれない場合、単なるFreeMemです。
キャストした場合はキャストした型の実体サイズがFreeMemのサイズとして用いられます。
これは実行時にCPUウィンドウを見ることで簡単に確認できます。
また、汎用ポインタを渡した場合はFreeMemにポインタだけ渡した場合と同じように処理されるため、
今回の場合はキャストをしなくても正しく解放することが可能です。


やましん  2010-12-11 08:27:03  No: 39698

早速のお返事ありがとうございます。
if ls.Add(pcc) = -1 then Dispose(pcc);
にて解決しました。
本当にありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加