【入門編】【上級プロ】巨大アセンブリ構築時におけるメモリリークを完全防止するための、COMオブジェクトの厳格な参照解放パターン – SolidWorks VBA解析バイブル

スポンサーリンク

こんにちは!SolidWorksを使った自動化の荒波に挑んでいる皆さん、先輩エンジニアの私です。

マクロの記録ボタンを押してコードを覗いてみたものの、「なんだこの呪文書は…」と途方に暮れたり、小さな部品を並べるだけのつもりが、部品点数が数千点を超えた途端にSolidWorksがフリーズして強制終了、「デスクトップに涙の未保存ファイル」という悲劇に見舞われたりしていませんか?

――大丈夫。ここをクリアすれば、あなたもSolidWorks VBAの本質を捉えた「真の自動化エンジニア」の仲間入りです。

今回は、数千点規模の巨大アセンブリを構築する際、VBAの裏側で何が起きているのか、そしてなぜマクロが突然クラッシュするのかという「メモリリークの闇」を完全に暴き、それを防ぐための極限の知見を授けます。

ここさえ押さえれば、大容量アセンブリの自動生成も怖くありません。一緒にバッチリマスターしていきましょう!

—

1. なぜ巨大アセンブリのループ処理でSolidWorksはクラッシュするのか?

数千個の部品をループ処理でアセンブリに配置していくコードを書いたとします。最初の100個はサクサク動くのに、500個、1000個と進むにつれて動作が重くなり、最終的に「メモリ不足(あるいはAutomation Error)」で落ちる……。

原因は、VBAの「ガベージコレクション(自動メモリ解放)の気まぐれ」と、COMオブジェクトの「参照カウントの呪い」にあります。

VBAとSolidWorks APIの裏側の関係

VBAからSolidWorksのAPI(`SwApp.OpenDoc6` や `AssemblyDoc.AddMate5` など)を呼び出すとき、VBAはWindowsの「COM(Component Object Model)」という仕組みを介してSolidWorks本体と会話しています。

APIを実行するたびに、SolidWorksのメモリ空間には「新しく作ったオブジェクト(部品や合致など)」の参照が生まれ、VBA側にもその窓口(ポインタ)が渡されます。

ここで恐ろしい事実があります。
「VBAは、ループを回している最中に自分がばら撒いたCOMオブジェクトの窓口を、すぐには片付けてくれない」のです。

VBAの変数(例:`Dim swComp As ModelDoc2`)をループ内で使い回したり、新しく代入したりしても、古いオブジェクトへの参照がメモリのゴミ(ゾンビオブジェクト)として背後に残っていきます。これが数千回積み重なると、SolidWorksのC++側のメモリが圧迫され、耐えきれずにクラッシュしてしまうのです。

—

2. 破滅を回避する「厳格な参照解放パターン」の極意

このメモリリークを防ぐ唯一にして最大の解決策。それは、「使い終わったCOMオブジェクトの変数を、コードの手で明確に『空(Nothing)』に戻す」ことです。

これこそが、巨大アセンブリを安定稼働させるためのプロの流儀です。

基本のルール

1. オブジェクトを変数に代入して操作したら、用事が済んだ瞬間に `Set 変数 = Nothing` を必ず書く。
2. ループの内部で生成される一時的なオブジェクト(コンポーネント、合致フィーチャーなど)は、1周終わるごとに必ず解放する。

言葉だけではピンとこないと思うので、実際のコード例を見てみましょう。

—

3. 【実践】メモリリークを完全封鎖するアセンブリ構築コード

以下に、数千点規模の配置を想定した、安全で堅牢なVBAコードのテンプレートを提示します。そのまま開発現場でコピペしてベースとして使えます。

Option Explicit

Sub BuildHugeAssembly_SafePattern()
Dim swApp As SldWorks.SldWorks
Dim swAssyDoc As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc

‘ アプリケーションのインスタンス取得
Set swApp = Application.SldWorks
Set swAssyDoc = swApp.ActiveDoc

‘ アクティブドキュメントがアセンブリかチェック
If swAssyDoc Is Nothing Then
MsgBox “アセンブリを開いてから実行してください。”, vbCritical
Exit Sub
End If
If swAssyDoc.GetType() <> swDocASSEMBLY Then
MsgBox “対象はアセンブリである必要があります。”, vbCritical
Exit Sub
End If

Set swAssy = swAssyDoc

‘ 処理速度向上のため、画面描画と自動再計算を停止(超重要!)
swApp.GetUserProgressBar(True) ‘ 画面更新停止の代わりなど
swAssyDoc.Visible = False ‘ 描画を隠すことでパフォーマンス向上

Dim i As Long
Dim componentPath As String
componentPath = “C:\MyParts\bolt.sldprt” ‘ 配置する部品のパス

Dim swModel As SldWorks.ModelDoc2
Dim swComp As SldWorks.Component2
Dim translated As Boolean

‘ — メインのループ処理(例:1000個配置する) —
For i = 1 to 1000

‘ 1. コンポーネントの挿入
‘ ※Component2オブジェクトが新しくメモリ上に生成される
Set swComp = swAssy.AddComponents3(componentPath, 0, i 0.05, 0, 0)

If Not swComp Is Nothing Then
‘ 必要であればここで合致(Mate)の処理を追加する
‘ Call CreateMate(swAssy, swComp, …)

‘ 【極意】使い終わったコンポーネントの参照を即座に解放する!
‘ これを怠ると、ループの回数分だけメモリリークが蓄積します。
Set swComp = Nothing
End If

‘ 定期的にVBAのメモリ解放(ガベージコレクション)を促す
If i Mod 100 = 0 Then
DoEvents ‘ Windowsに処理を譲る
End If

Next i

‘ 画面描画の復元
swAssyDoc.Visible = True
swAssyDoc.ForceRebuild3 (False)

‘ ループ外で使ったルートオブジェクトの解放
Set swAssy = Nothing
Set swAssyDoc = Nothing
Set swApp = Nothing

MsgBox “アセンブリの構築が正常に完了しました!メモリリークも完璧に防止されています。”, vbInformation

End Sub

コードの解説:ここがエンジニアのこだわりポイント

  • `Set swComp = Nothing` の位置

ループの最後、その周回での作業が終わった瞬間に `Nothing` を代入しています。これにより、VBAが保持していたCOMコンポーネントへの参照カウントが即座にデクリメント(減算)され、ゴミとして回収されます。

  • 画面描画の非表示化 (`Visible = False`)

オブジェクトを1つ追加するたびにSolidWorksが画面を再描画していると、それだけで処理が何倍も遅くなります。巨大アセンブリを扱うときは、描画をオフにしてバックグラウンドで黙々と処理させるのが鉄則です。

  • `DoEvents` の挟み込み

100回に1度 `DoEvents` を入れることで、OSやSolidWorksが内部のメモリ管理やイベント処理を行う隙を与え、フリーズを防ぎます。

—

4. 陥りやすい罠とエラー対策

最後に、初心者がやりがちな「やってはいけないミス」をいくつか挙げておきます。

1. エラー処理(`On Error GoTo`)をサボる
もしループの途中でエラーが発生してマクロが中断した場合、その時点で解放処理(`Set … = Nothing`)がスキップされ、メモリリークしたままマクロが終了してしまいます。
本番のコードでは必ず `On Error GoTo ErrorHandler` を仕込み、エラー時でも確実にオブジェクトを解放するブロックを通すようにしましょう。

2. オブジェクトの連鎖取得に注意
`swAssy.GetFirstComponent2.GetModelDoc2` のように、ドット(`.`)で繋いで一気にオブジェクトを取得すると、途中に隠れた一時オブジェクトの参照が解放できなくなります。
面倒でも、1つずつ変数に受けて、使い終わったら個別に `Nothing` を入れるのがプロの作法です。

—

まとめ

いかがでしたでしょうか?
今回は、巨大アセンブリ構築におけるメモリリークの恐怖と、それを完全封鎖する「COMオブジェクトの厳格な参照解放パターン」について解説しました。

  • ループ内で生成するオブジェクトは、必ずその周回内で `Set … = Nothing` で解放する。
  • 画面描画を切り、バックグラウンドで処理することでパフォーマンスと安定性を爆上げする。

この基本原則さえ体に染み込ませれば、数千点規模の巨大アセンブリを自動生成するマクロも、エラー知らずで軽快に動いてくれるはずです。

あなたのSolidWorks自動化ライフが、クラッシュの恐怖から解放され、快適で知的なものになることを応援しています。それではまた、次の極限の知見でお会いしましょう!

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