質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

9414閲覧

VBAのSet 変数 = Nothingの対象とタイミングをご教示ください

退会済みユーザー

退会済みユーザー

総合スコア0

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2022/06/14 15:09

編集2022/06/14 15:32

VBA初心者の新人プログラマーです。
VBAのSet 変数 = Nothingの対象とタイミングをご教示ください。

①Set 変数 = Nothingの対象
変数に対して、処理後にメモリ解放が必要とざっくり理解しております。
変数の中でも「参照を行っている変数」に対して必要とのことですが、その判断はコードの作り次第なのでしょうか?
例として、下記コードを作成しました。質問箇所のご確認をお願いします。

VBA

1'変数の宣言 2Dim ws_sheet1 As Worksheet 3Dim str_name As String 4Dim str_kaisya As String 5Dim cn As Object 'ADO接続に使用する変数 6Dim rs As Object 'ADO接続に使用する変数 7 8On Error GoTo myError 9 10'変数のset 11Set ws_sheet1 = Worksheets("明細") 12Set str_name = ws_sheet1.Range("A1").Value 13Set str_kaisya = "TEST会社" 14 15'ADO接続・処理箇所は省略します 16rs.Open '省略... 17cn.Open '省略... 18 19rs.Close 20cn.Close 21 22'●●●●質問箇所●●● 23'解放が必要と思われる変数 24Set ws_sheet1 = Nothing 25Set rs = Nothing 26Set cn = Nothing 27 28'解放が必要でしょうか? 29Set str_name = Nothing 30Set str_kaisya = Nothing 31 32myError: 33'解放が必要と思われる変数を記載 34MsgBox "エラー" 35Exit Sub 36 37End Sub

②Set 変数 = Nothingのタイミング
End sub直前にメモリ解放を必要性はあるのでしょうか?
まず自身のメモリ解放についての認識ですが、誤りがある場合ご指摘をお願いします。
参照範囲が大きい変数は、処理毎に解放を行う必要があり、End subで暗黙的にメモリ解放が行われる認識です。
上記コードのように参照範囲が大きくなく、プロシージャ間の受け渡しがない場合、メモリ解放は必要でしょうか?※ADOのObjectはほとんどの場合において必要との認識です。

ネットで調査したところ、「End sub直前は不要」「エラー発生時等の保守性を考慮して書いておくべき」と双方のご意見があるようです。

以上です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2022/06/14 15:38

> 新人プログラマーです。 先輩に確認するのが良いかと思います。御社のコード規約に従えば良いのではないでしょうか?
退会済みユーザー

退会済みユーザー

2022/06/14 15:55

回答ありがとうございます。まずコード規約につきまして、弊社ではVBA開発実績がないため、規約も特にありません。そのため一般的な規約に沿ったものを開発する方針です。 また開発実績のある先輩がおらず、触れたことのある先輩に確認をしましたが、よく分からないままの現状で困っています。以下確認した結果です。 ○メモリ解放の対象→(回答)オブジェクト変数 ○メモリ解放のタイミング→(回答)End sub前に必要 ※VBAの慣例だから
guest

回答3

0

ベストアンサー

この話はなかなか奥が深いので、説明しだすと長くなりますので、下記あたりを参照してみてください。

VBA Set Obj = Nothing は必要か - t-hom’s diary

VBAのメモリ管理については、

VBA 変数とメモリの関係 ~ 値渡しと参照渡しをメモリの動きから理解する - t-hom’s diary
VBA オブジェクトとメモリの関係 ~ オブジェクトが参照型と呼ばれる理由 - t-hom’s diary

結論だけいうと、
VBAはメモリを参照カウント方式で管理している。
どこからも参照されなくなったときオブジェクトは破棄されメモリは解放される。
モジュール内変数なら、End Subを抜けたとき参照はなくなるので、
Set オブジェクト変数 = Nothing
は特に必要ない。

ただし、自己参照や循環参照があると参照が消えないのでオブジェクトが破棄されずメモリ上にのこる場合があります。
あと、外部参照のオブジェクト(IE とか、ADOなど)は、それ自身がもつクローズメソッド(QuitとかClose)で破棄する必要があります。

投稿2022/06/15 02:01

編集2022/06/15 03:31
hatena19

総合スコア33699

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/06/15 02:30

回答ありがとうございます。URLも拝見しました。 >どこかも参照されなくなったときオブジェクトは破棄されメモリは解放される。 >ただし、自己参照や循環参照があると参照が消えないのでオブジェクトが破棄されずメモリ上にのこる場合があります。 「自己参照や循環参照がない」という判断を正しくできていれば、End Subを抜けたときにメモリ上に残らないのですね。 保守を考慮する場合、この判断のリスクが伴うことを理解しました。コード規約で制限される理由も納得です。
guest

0

変数に対して、処理後にメモリ解放が必要とざっくり理解しております。

いいえ。解放するのは変数じゃなくてオブジェクトです。

変数の中でも「参照を行っている変数」に対して必要とのことですが、

オブジェクトへの参照をSet文で代入した変数に対して、Nothingを代入することで、さっきまで代入されていたオブジェクトへの参照を断ち切ってそのオブジェクトが不要であることを処理系に知らせます。

その判断はコードの作り次第なのでしょうか?

はい。
プログラム終了の直前で明示的に解放する意味は無いです。プログラムが終わればプロセスまるごと無くなるので。
また、変数の有効範囲からEnd Sub等で抜ける場合は、ローカル変数へのNothingの代入も不要です。
明らかに不要である場合以外の場面で、不要となったオブジェクトへの参照が代入されていた変数に対して、明示的にNothingを代入するかどうかはそのオブジェクトがメモリ上に残り続けることによる影響に依ります。

単に、毎回考えれば良いだけの話なので、機械的な一律ルールを決める意味は無いでしょう。

投稿2022/06/14 22:25

otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/06/14 23:32

回答ありがとうございます。メモリ解放の対象を理解しました。 またメモリ解放の判断は、使用方法や使用箇所を考慮して一つずつ判断する必要があるのですね。 意味がないEnd sub前でのメモリ解放は、「メモリに残る可能性のある変数を判断することを省く」保守を考慮した意図なのではないかと感じました。
guest

0

変数に対して、処理後にメモリ解放が必要

言語上は、特に必要ありません。VBA環境にはガベージコレクタが存在しますので、不要となった変数は関数などスコープが終わるタイミングで無効化されます。

投稿2022/06/14 21:35

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/06/15 02:23 編集

回答ありがとうございます。VBAのメモリ解放は、ガベージコレクタがないため行っているものだと思い込んでいました。認識を改めます。
hatena19

2022/06/15 01:26

残念ながら、VBAにはガベージコレクタは未実装だと思います。VBAのバージョンアップはVB7で止まっていますので。VB.NETではガベージコレクタは実装されていますが。
hatena19

2022/06/15 01:52

参照カウント方式でメモリ管理している。(これもガベージコレクタの一種という考え方もあるようです。) これにより「End Sub」前に Set オブジェクト変数 = Nothing が必要ないということはあります。
maisumakun

2022/06/15 02:05

> 参照カウント方式でメモリ管理している。(これもガベージコレクタの一種という考え方もあるようです。) そうですね、「C言語のような、自分でのfreeが不要」という意味合いで「ガベージコレクタ」という単語を使っていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問