web-dev-qa-db-ja.com

VBA関数内でObjectsをNothingに設定する必要がありますか

オブジェクトを使い終わったら、オブジェクトを何も設定しないことをお勧めします。ただし、通常はフォーム内の関数でのみ使用します。

オブジェクトをNothingに設定するかどうかに関係なく、関数スコープを離れると参照が失われ、メモリが解放されませんか?

すなわち、本当にする必要があります:

Set db = Nothing
Set record_set = Nothing
60
Ramon

VBは、いわゆる「参照カウント」ガベージコレクターを使用します。

基本的に、変数がスコープから外れると、参照されるオブジェクトの参照カウンターは減分されます。オブジェクト参照を別の変数に割り当てると、参照カウンターが増分されます。

カウンターがゼロに達すると、オブジェクトはガベージコレクションの準備ができています。オブジェクトリソースは、これが発生するとすぐに解放されます。関数ローカル変数は、参照カウントが1より大きくならないオブジェクトを参照する可能性が高いため、オブジェクトリソースは関数の終了時に解放されます。

変数をNothingに設定すると、参照カウンターを明示的に減らすことができます。

たとえば、ファイルを読み込み、ReadAll()呼び出しの直後にファイルオブジェクト変数をNothingに設定します。ファイルハンドルはすぐに解放され、コンテンツの処理に時間をかけることができます。

Nothingに設定しない場合、ファイルハンドルは絶対に必要な時間より長く開いている可能性があります。

「貴重なリソースのブロックを解除する必要がある」ような状況にない場合は、変数をスコープから外すだけでかまいません。

71
Tomalak

ガベージコレクションが完璧になることはめったにありません。 .NETでも、システムにガベージコレクションを早期に行うように促すことが強く推奨される場合があります。

このため、処理が完了したらcloseNothingの両方のレコードセットを明示的に設定します。

14
BIBD

Microsoft DAOヘルプおよびAccess Developer Referenceの「 Recordset.Close 」のヘルプトピックの最後の行は次のとおりです。

「Closeメソッドの代替方法は、オブジェクト変数の値をNothingに設定することです(Set dbsTemp = Nothing)。」

http://msdn.Microsoft.com/en-us/library/bb243098.aspx

この記事 「データアクセスオブジェクト(DAO)を使用した後のデータベースの膨張を防ぐ方法」というタイトルのマイクロソフトサポート技術情報から、必要ない場合は明示的に閉じる必要があることを示します。データベースを肥大化します。この記事は詳細については少し曖昧であることに気付くでしょう。 「原因」セクションは不明瞭で、ほとんど意味不明です。

http://support.Microsoft.com/kb/289562

現象:データアクセスオブジェクト(DAO)を実装してレコードセットを開くと、Microsoft Accessデータベースが膨張し始めます(またはサイズが急速に大きくなります)。

原因:レコードセットコードをループするたびにレコードセットのメモリを解放しないと、DAOはより多くのメモリを使用してデータベースのサイズを増やして再コンパイルする場合があります。

詳細:コードでRecordset(またはQueryDef)オブジェクトを作成する場合、終了したらオブジェクトを明示的に閉じます。 Microsoft Accessは、ほとんどの状況でRecordsetおよびQueryDefオブジェクトを自動的に閉じます。ただし、コード内でオブジェクトを明示的に閉じると、オブジェクトが開いたままのときのインスタンスを回避できます。

最後に、15年間Accessデータベースを操作してきました。また、Closeメソッドを明示的に使用せずに、ローカルで宣言されたレコードセット変数をほとんど常にスコープから外します。私はそれについて何もテストしていませんが、それは問題ではないようです。

13
Shane Miskin

ASPクラシック(サーバー側スクリプト))を使用している場合、すべてのオブジェクトは、[virtual ]サーバーがシャットダウンされました。

このため、すべてのMS VB=スクリプトの例では常にオブジェクトが閉じられ、何も設定されていません。スクリプトの抜粋はASPオブジェクトが範囲外にならない場合。

まれに、オブジェクトがスコープ外にならない長期実行プロセスをコーディングしたい状況があり、オブジェクトを明示的に解放しないと物理メモリが不足することがあります。

ASP classic、または他の何らかの理由でプロセスをグローバルスコープで実行している場合、はい、オブジェクトを明示的に解放する必要があります。

2
david

参照は、変数がスコープから外れるとクリーンアップされることになっています。おそらくこれは後のバージョンのソフトウェアで改善されたと思われますが、かつては信頼できませんでした。変数を明示的に「Nothing」に設定することは良い習慣であると思います。

2
John Mo

私は通常、これを私の手順の最後に常に置くか、モジュールレベルのものを使用している場合は、それを使用して「CloseRecordSet」サブルーチンを呼び出します。

Private Sub Rawr()
On Error GoTo ErrorHandler

    'Procedural Code Here.

    ExitPoint:
        'Closes and Destroys RecordSet Objects.
        If Not Recset Is Nothing Then
            If Recset.State = 1 Then
                Recset.Close
                Conn.Close
            End If
            Set Recset = Nothing
            Set Conn = Nothing
        End If
        Exit Sub

    ErrorHandler:
        'Error Handling / Reporting Here.
        Resume ExitPoint
End Sub

そのようにすると、プロシージャは終了します(通常またはエラーのため)。オブジェクトはクリーンアップされ、リソースは解放されます。

その方法でそれを行うことは非常に安全であり、ただそれをたたくだけで、レコードセット/接続オブジェクトが既に閉じられている場合(ランタイムエラーまたは必要に応じて早めに閉じてください。

面倒なことはほとんどなく、プログラムで何が起こっても、すぐにオブジェクトをクリーンアップしてリソースを解放するのが最善です。

1
BobT