VBAのメモリー管理は 参照カウンタ方式
です。仕組みはシンプルですが、漏れ無く開放
するにはそれなりの注意が必要です。
まずは、自分が以前に同様の問題の解決に役立ったページをご連携致します。実際にはかなり膨大な数のページを参照しましたが、とりあえず主だったものを3つだけ…
4.1.5 オブジェクト消滅の管理
Excelのプロセスが正常に終了しない理由(その1)
15.消えないExcelのプロセス
Excel VBA以外の話題も含まれていますが、原理は同じです。ちょっと長いのですが、辛抱して注意深くお読みください。
要点を簡単にまとめると、
- メモリーリークが発生するのは参照カウンタが0になっていないために開放されないオブジェクトがあるから
- 使用済みオブジェクトを確実に開放するには使用済みオブジェクトの参照カウンタを確実にデクリメントする
- 「暗黙の参照」が発生しないように気をつける
このうち、一番面倒なのが、最後の『暗黙の参照を発生させない』という点です!
これは口で言うのは簡単なのですが実践するとなると結構面倒です。
自分はまだExcelのオブジェクトモデルの全容を把握出来ていないので、どこまでやれば必要十分で確実なのかが分からないのですが、以下のようなコーディング方法はオブジェクトの開放漏れを発生させてしまうようです。
- オブジェクトを省略してプロパティを指定する
- 参照する個々のオブジェクトを逐一変数で受けずに使用する
2番目の『逐一変数で受ける』というのは分かりにくいですが、平たく言えば .
(ピリオド)が2つ以上繋がるようなコーディング方法は暗黙の参照を引き起こし、オブジェクトの開放漏れに繋がる可能性があるということです。
ですから、(冗長な部分もあるかもしれませんが)参照カウンタを確実にデクリメントしてオブジェクトの開放漏れを防ぐには、以下のようなコーディング方法が必要ということになります。
(修正前)
Worksheets("Sheet1").OLEObjects("LblTackt").Object.Caption = CStr(iTimer4)
(修正後)
Dim xlApp As Excel.Application
Dim xlBook As Worksheet
Dim objOle As Object
Dim objTarget As Object
Set xlApp = GetObject(, "Excel.Application")
Set xlBook = xlApp.Worksheets("Sheet1")
Set objOle = xlBook.OLEObjects("LblTackt")
Set objTarget = objOle.Object
objTarget.Caption = CStr(iTimer4)
Set objTarget = Nothing
Set objOle = Nothing
Set xlBook = Notihng
Set xlApp = Nothing
Excel VBA は気軽に手間なく実装出来るところが最大の魅力でもあるので、いわゆる手抜きをしたコーディング方法でも適宜暗黙の参照を適切に扱い実行可能にしてくれます。
扱うオブジェクトのサイズが小さかったり、ループ回数が少ない場合には、メモリーの枯渇が顕在化する前に作業が完了してExcelのブックを閉じてしまうので、細かいことを気にしなくても全く問題ありません。
しかし、
- 巨大なオブジェクトを扱う
- ループの回数が多い
- 長時間プログラムを実行し続ける
などの場合には、参照カウンタのデクリメントを意識しながら使用の終わったオブジェクトを確実に開放しないと、メモリーリソースがすぐに枯渇して実行時エラーが発生してしまいます。
ですので、必ずしも全てを上記のような面倒なコーディング方法にしなくても良いと思いますが、
- サイズの大きなオブジェクトを扱う場合
- 繰り返し回数の多いループの中でオブジェクトを扱う場合
については、参照カウンタを明示的にデクリメントできるような実装方法を心がけてみてください。
以上、幾らかでもご参考になれば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/12/23 15:58