この人頭いいなと思ったエピソード

こんばんは。

プロシージャレベルで宣言したWorksheetやRangeなどのオブジェクト変数に対し、
プロシージャを終了する直前に、
Set ○=Nothing
を実行して、変数(オブジェクトへの参照)を開放する処理を習慣的行っていました。

これは、絶対に必要な処理なのでしょうか?
開放しないことで不具合が出るケースとはどういう場合なのでしょうか?

どなたか、ご教示いただけないでしょうか。
よろしくお願いいたします。

<例>
Sub test()
  Dim Ws1 As Worksheet
  
  Set Ws1 = Worksheets("Sheet1")

  '処理内容
  
  Set Ws1 = Nothing
End Sub

尚、CreateObject関数で作成したオブジェクトへの参照などではなく、
あくまでもWorksheetやRangeなどの話です。

A 回答 (2件)

プロシージャレベルの Worksheet や Range オブジェクトでは、


プロシージャの終了とともに自動開放されますから、 Nothing に
よる開放処理は必須ではありません。

長く VBA を使っておりますが、省略したからといって不具合が発生
したケースも経験ありません。

ただ、プログラムを書く姿勢として、

  自分で使ったモノは、自分で開放する

とあるべきではないかと考えます。

VBA においてはマナーみたいなものですね。されど、これは私個人
だけの考えではなく、過去から積み上がった先人プログラマーの
経験側でもあります。

例えば、VBA のこのような言語仕様に慣れきった人、つまり開放
するということが習慣として身についていない人が、メモリ操作や
画像処理など高度な処理を書くようになった場合、必須の開放処理
が抜け落ちたプログラムを平気で書いてしまい、後々メモリリーク
に悩むはめになったりしがちです。

言語仕様として、「必須ではない」とはいえ、きちんと開放処理を
記述した方が良いでしょう。

注意が必要なのは、オートメーションを使ったプログラムの場合は、
例えプロシージャレベルであっても開放必須です。これを怠ると
#1 でお話がでてますが、いわゆるゾンビプロセスが残るという事態
になります。また、

> プロシージャレベルで宣言したWorksheetやRangeなどの...

と限定されているのでお分かりかと思いますが、グローバル等の
広域変数の場合も、誤動作防止、余計なメモリ消費を抑えるため
適所で開放処理が必須になります。

余談になりますが、#1 補足欄のソースは私ならこう書きます。
ご参考までに。

Sub test()
  On Error Goto Err_
  Dim Ws1 As Worksheet
  Set Ws1 = Worksheets("Sheet1")

  '処理内容
  
Bye_:
  Set Ws1 = Nothing
  Exit Sub
Err_:
  'エラー処理
  Resume Bye_
End Sub
    • good
    • 1
この回答へのお礼

KenKen_SP様、大変丁寧なご回答ありがとうございました。

すっきり納得できました。

必須ではないが、行うべきだということですね。

最後のソースを含め大変参考になりました。

またお世話になる事があると思いますが、
その際はよろしくお願いいたします。

お礼日時:2009/12/16 19:11

Nothingは必要であると思ってます。



VBAのつくりが悪くて、何度かNothingを通る前に強制終了させてたらフリーズ。
タスクマネージャでプロセスみたら、EXCELの残ったままのプロセスが・・・。(ゾンビプロセス?)


なので、「おまじないかも?」とは思いつつも実行してます。

この回答への補足

ご回答ありがとうございます。

途中でエラーが発生した場合のことを考えて
ということですね。

それでは、以下のような処理をしたほうが
良いのでしょうか?
(Exit Subの前では、あえてNothingしてません)

<例>
Sub test()
  On Error Goto Err
  Dim Ws1 As Worksheet
  
  Set Ws1 = Worksheets("Sheet1")

  '処理内容
  
  Exit Sub

Err: 
  Set Ws1 = Nothing
End Sub

補足日時:2009/12/15 17:51
    • good
    • 0
この回答へのお礼

bin-chan様 ご回答ありがとうございました。

今までどおり、変数の開放を習慣化しようと思います。



以下、備忘録として利用させていただく事をお許しください。

Sub test()
  On Error Goto Err_
  Dim Ws1 As Worksheet
  Set Ws1 = Worksheets("Sheet1")

  '処理内容
  
Bye_:
  Set Ws1 = Nothing
  Exit Sub
Err_:
  MsgBox Err.Description, vbCritical
  Resume Bye_
End Sub

お礼日時:2009/12/16 20:16

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報

このQ&Aを見た人がよく見るQ&A