【実務・中級編】【インスタンス作成監視】Class_Initialize と Class_Terminate を用いた自作オブジェクトのリーク診断カウンター – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptの「見えない墓標」を可視化せよ:Class_Terminateで実現するリーク診断の極意

VBScriptは、その簡潔さゆえに「使い捨てのスクリプト言語」と侮られがちだ。だが、業務自動化の現場で数万行規模のRPAスクリプトを組むエンジニアにとって、この言語は「メモリ管理のブラックボックス」そのものである。

特に、`Class`構文を多用する設計において、オブジェクトの生成と破棄のサイクルを掌握できていないコードは、いずれ必ず「サイレント・メモリリーク」という名の時限爆弾を抱えることになる。

今日は、場当たり的なデバッグに頼るのをやめ、「オブジェクトのライフサイクルを可視化する」ための、プロフェッショナルな実装手法を伝授する。

—

なぜVBScriptで「破棄漏れ」が起きるのか

VBScriptのガベージコレクションは参照カウンタ方式だ。しかし、循環参照や予期せぬグローバル変数の保持、あるいはエラーハンドリングの不備によって、オブジェクトが解放されないケースは多々ある。

特に、DB接続やファイルハンドラを抱えたクラスがメモリ上に残留した場合、それは単なるメモリリークに留まらず、「ファイルロック」や「DBセッションの枯渇」という致命的な運用障害に直結する。

解決策:Staticカウンターによる「生存確認」

各クラスの `Class_Initialize`(生成時)と `Class_Terminate`(破棄時)にカウンターを仕込む。これだけで、現在システム上に何個のインスタンスが「死に損なっているか」を瞬時に特定できる。

—

実装:リーク診断カウンターを搭載したクラス設計

以下のコードは、単なるデバッグ用ではない。プロダクション環境のデバッグモードで動かすことを想定した、保守性の高いテンプレートだ。

‘ 診断用のデバッグクラス
‘ 本番環境ではこの変数をFalseにすることでオーバーヘッドをゼロにする
Const DEBUG_MODE = True

‘ クラスの生存数を追跡するためのグローバルスコープ(または管理クラス)
Dim g_InstanceCounter : g_InstanceCounter = 0

Class ResourceHandler
‘ インスタンス生成時にカウントアップ
Private Sub Class_Initialize()
If DEBUG_MODE Then
g_InstanceCounter = g_InstanceCounter + 1
WScript.Echo “[DEBUG] インスタンス生成: 現在の生存数 = ” & g_InstanceCounter
End If
End Sub

‘ インスタンス破棄時にカウントダウン
Private Sub Class_Terminate()
If DEBUG_MODE Then
g_InstanceCounter = g_InstanceCounter – 1
WScript.Echo “[DEBUG] インスタンス破棄: 現在の生存数 = ” & g_InstanceCounter
End If
End Sub

‘ 実際の業務ロジック
Public Sub DoWork()
WScript.Echo “処理を実行中…”
End Sub
End Class

‘ — メイン実行部 —
Set obj = New ResourceHandler
obj.DoWork()

‘ 意図的に解放する
Set obj = Nothing

‘ 最後に残骸がないかチェック
If g_InstanceCounter > 0 Then
WScript.Echo “警告: ” & g_InstanceCounter & ” 個のオブジェクトが解放されていません。”
End If

—

堅牢な設計のための3つの鉄則

コードをコピペして終わりにしてはならない。現場で生き残る自動化ツールを作るためには、以下の設計思想を骨の髄まで叩き込む必要がある。

1. `Set obj = Nothing` の強制

VBScriptにおいて `Nothing` への代入は単なる儀式ではない。スコープが終了するまでメモリが解放されないケース(特にループ内での大量生成)では、明示的な解放は必須だ。

2. エラーハンドリングとの統合

`On Error Resume Next` を使用している場合、例外発生時に `Class_Terminate` が期待通りに呼ばれないシナリオを想定せよ。`Err.Clear` を呼ぶ前に、必ずリソースのクリーンアップ処理(`Close`メソッドなど)を通すメソッドチェーン設計を心がけること。

3. ファイル・DB接続は「ラップ」せよ

生のリソース(ADODB.Connection等)をクラスのプロパティに直接公開してはいけない。必ず「Closeメソッド」を持つ独自クラスでラップし、そのクラスの `Class_Terminate` 内で確実に `Close` メソッドを呼ぶよう設計せよ。これにより、万が一破棄漏れが発生しても、オブジェクトが解放されるタイミングで接続が閉じるという「二段構えの防衛」が機能する。

—

最後に:エンジニアとしての誇り

「動けばいい」というコードは、誰でも書ける。しかし、「なぜ動いているのか」「どこで死ぬ可能性があるのか」をコード自体に語らせるのが、真のエンジニアだ。

このカウンターを実装し、テスト実行でログを確認してほしい。もし終了時にカウンターが0以外の数字を表示したなら、君のコードには「見えない墓標」が立っているということだ。

その墓標を一つずつ消し去ることこそが、システムを安定させ、君自身の業務負荷を激減させる唯一の道である。さあ、今すぐコードを書き換え、自身の書いたオブジェクトたちを完璧に支配下に置くのだ。

タイトルとURLをコピーしました