【AutoCAD VBA】メモリリークを根絶せよ:堅牢な図面制御のための「アーキテクトの作法」
AutoCADのオートメーションにおいて、最も「素人」が陥りやすく、かつ「プロ」が最も忌み嫌うのが図面開閉時のメモリリークだ。
「マクロを走らせると、図面を閉じるたびにAutoCADが重くなり、最終的にクラッシュする」
もし君の現場でそんな現象が起きているなら、それは君のコードがAutoCADのオブジェクトライフサイクルを正しく制御できていない証拠だ。
今日は、表面的なAPIの使い方は知っているが「なぜメモリが解放されないのか」を理解していない中級者向けに、現場の品質を劇的に向上させる高度なオブジェクト管理術を叩き込む。
—
1. なぜ「`Set doc = Nothing`」だけでは足りないのか
多くの初学者は、`Set doc = Nothing` を書けばメモリが解放されると信じている。だが、AutoCADのCOMオブジェクトはそんなに甘くない。
AutoCADのAPIにおいて、`Application.Documents.Open` で取得した `Document` オブジェクトは、強固な参照カウントを持っている。特に、イベントハンドラやバックグラウンドプロセスが絡む場合、オブジェクトへの参照が「隠れた形で」残り続け、ガベージコレクション(GC)が機能不全に陥る。
致命的なアンチパターン
‘ 悪い例: 参照を放置し、エラーハンドリングを怠る
Sub BadPractice()
Dim doc As AcadDocument
Set doc = Application.Documents.Open(“C:\Project\Data.dwg”)
‘ 何か処理…
doc.Close True
Set doc = Nothing ‘ これだけでは不十分な場合が多い
End Sub
このコードが危険な理由は、`Close` メソッドが呼び出された瞬間にAutoCAD側でオブジェクトが破棄される可能性があるにも関わらず、VBA側の変数 `doc` がその「幽霊」を指し続けているからだ。
—
2. 堅牢な図面オープン・クローズの鉄則
プロフェッショナルが書くコードには、「生存確認」と「強制解放」の二重構造が必要だ。以下のコードは、私のプロジェクトで標準採用している「安全な図面操作」のテンプレートである。
実践的なプロダクションコード
Public Sub SafeOpenAndClose(ByVal filePath As String)
Dim targetDoc As AcadDocument
On Error GoTo ErrorHandler
‘ 1. ファイルの存在確認(初歩だが重要)
If Dir(filePath) = “” Then Err.Raise vbObjectError + 1, , “ファイルが存在しません。”
‘ 2. 図面オープン
Set targetDoc = Application.Documents.Open(filePath)
‘ — ここに業務ロジックを記述 —
Call ExecuteHeavyTask(targetDoc)
‘ —————————-
‘ 3. 明示的な保存と終了
If Not targetDoc Is Nothing Then
targetDoc.Close True ‘ 保存して閉じる
End If
Cleanup:
‘ 4. 強制的なメモリ解放
‘ 参照が生きている場合は明示的に破棄を試みる
If Not targetDoc Is Nothing Then
Set targetDoc = Nothing
End If
Exit Sub
ErrorHandler:
MsgBox “エラー発生: ” & Err.Description
Resume Cleanup
End Sub
—
3. 大規模データ処理における「暗黙の罠」
もし君が数百枚の図面をループ処理で開閉するツールを作っているなら、以下の「ドキュメント・ロック」の概念を理解しなければならない。
AutoCADは図面を開く際、ロックファイルを生成する。連続処理でメモリリークが発生すると、AutoCADがプロセスを終了させてもロックファイルが残り、次回のオープンに失敗したり、メモリ使用量が肥大化し続ける。
パフォーマンスを維持する極意:
1. DoEventsの適切な配置: 大量処理時は `DoEvents` を入れないとOSレベルでリソースの解放が追いつかなくなる。ただし、入れすぎるとパフォーマンスが落ちる。50図面ごとの「休憩」が最適解だ。
2. Document.Closeの前後にPauseを入れる: 非常に稀だが、COMがオブジェクトを完全に破棄する前に次の操作を行うと、ハングアップの原因になる。`Application.Update` を挟むのがコツだ。
—
4. チーフアーキテクトからの提言
VBAは古臭い言語だと思われがちだが、AutoCADの内部COM制御においては、依然として最強のツールだ。しかし、その強力な権限は「責任」とセットであることを忘れてはならない。
- スコープを最小化せよ: ドキュメントオブジェクトをモジュールレベル変数にするな。必ずプロシージャ内で完結させ、使い終わったら即座に捨てろ。
- エラーハンドラは必須: 図面が開けなかった場合、開いた後の例外で処理が止まると、その図面は「開いたまま」バックグラウンドに残り続ける。これこそがメモリリークの最大の要因だ。
君たちが書くコードは、単なる自動化ツールではない。会社の資産を守り、設計者の工数を削減する「生産性エンジン」だ。メモリの1バイト、処理の1ミリ秒にまで執着するエンジニアであれ。
もしさらに深い「.NETによる非同期処理」や「ObjectARXとの連携」に興味があれば、またいつでも門を叩いてほしい。現場からは以上だ。
