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);で確保されたメモリを開放されてないのではないかと思うのですが、どうにも解決できません。
どなたかお解かりになる方いらっしゃいませんか?
Disposeに与えるポインタは正しい型の変数でなくてはいけません。
× Dispose(PColorCount(ls[nnum]));
○ var pcc: PColorCount; pcc := PColorCount(ls[nnum]); Dispose(pcc);
lsをClearしたりする際にも同様の注意が必要です。
そもそも、いったん追加してから削除するよりは、最初から「数が上限だったら追加しない」とした方が話が簡単だと思いますが……
1行目のorをandに変えたら解決したりしませんか?
>やましんさん
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にポインタだけ渡した場合と同じように処理されるため、
今回の場合はキャストをしなくても正しく解放することが可能です。
早速のお返事ありがとうございます。
if ls.Add(pcc) = -1 then Dispose(pcc);
にて解決しました。
本当にありがとうございました。
ツイート | ![]() |