[[20231130163948]] 『オブジェクトの解放』(うぃる) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『オブジェクトの解放』(うぃる)

 Sub test()
    Dim Dic As Object
    Set Dic = CreateObject("Scripting.Dictionary")

    '中間コード

    Set Dic = Nothing
 End Sub

 のようなコードで、最後の「Set Dic = Nothing」って
 必要なんでしょうか?
 「End Sub」に行ったらオブジェクトは勝手に解放されると思ってたんですが・・。

< 使用 Excel:Microsoft365、使用 OS:Windows11 >


この辺りに説明されているんじゃないかと思います。

https://www.moug.net/tech/exvba/0150027.html

P.S.

オブジェクト変数とオブジェクトは別物で、
オブジェクト変数はオブジェクトを参照している
みたいな理解は必要なのかなと思います。

簡単に言えばポインタです(よけい分からんか(^^;)
(ゆたか) 2023/11/30(木) 16:51:21


 回答ありがとうございます。参考になりました。

 > オブジェクト変数とオブジェクトは別物
 はい、この辺は理解しているつもりです。

 ただ、「Set Dic = Nothing」を「End Sub」の直前に入れている
 コードをよく見かけます。
 ほんとに必要なのかな・・??と思った次第です。
 コードの途中で解放ならまだわかるんですけど。
 いらないですよね!?

 ところで、ポインタってなんです?
(うぃる) 2023/11/30(木) 16:58:00

 >ただ、「Set Dic = Nothing」を「End Sub」の直前に入れている
 ?コードをよく見かけます。
 その変数がどこで宣言されているかによりませんかね

 Procedureレベルの変数であれば、Procedure終了時に自動で参照カウントが-1されますが
 Module以上のレベルの変数であれば、参照カウントは減らないんじゃないですか
(´・ω・`) 2023/11/30(木) 20:54:13

私は必ず入れています。

私の書き方は「If〜End If」と同じように
Set Dic = CreateObject("Scripting.Dictionary")
Set Dic = Nothing
と入力してから、上記2行の間にコーディングしています。

理由は、私が頭が悪いからです。
ゆかた様が掲載してくれたサイトの補足にある部分です。

Dictionaryなら大丈夫かもしれませんが、
InternetExplorer.Application
だと、どこでどのように他のオブジェクトと循環参照になっているか
明確にはわからない、もしかしたら他のオブジェクトと関係してるかもしれない
という感じで、私には曖昧な部分が多いのでNothingは入れています。
それが、たとえEnd Subの直前だろうが、
曖昧であれば入れておくに越したことはない(メモリにごみが残らない)
という感じです。

現在のPCのメモリ容量を考えれば、
不必要とも思えますが、私が、VB、VBAを始めたころは、
「メモリにごみが残ることは極力避ける」と
先輩方に教わりました。

又、「Nothingを入れたコードと、
入れていないコードの実行速度を比べてみても、
大差はない」とも教えられたので、
常にNothingを入れて書くことが習慣になっています。

間違えている部分等があれば、ご指摘いただければ幸いです。

(匿名) 2023/11/30(木) 22:11:54


 なるほど。
 最後にNothingセットするのって、機械側の都合というよりは人間様の都合を考慮しての事なんでしょね。

 Nothingをセットする事を「解放」と表現する場面、確かにちょいちょい見かけるんですけど、
 あれ「切断」と表現した方がニュアンス近いんじゃないかなぁと思ってます。
 「解放」だとどうしてもメモリの解放と混同してしまう。

 変数とオブジェクトとの通信を切断しただけ。例えるなら電話切っただけ。みたいな...
 あ
 でも、そんなこと言ったら「てめ、電話切らずに帰っちゃうんかよwww」って事にもなるから
 やはり最後にNothingセットするのが作法なんじゃない? とも考えられますよね ^^:

 「Nothingはメモリの解放」っていう勘違いがないなら、
 「要否」の話ではなく単に「好み」だとか「クセ」のお話に過ぎないので自由でしょう。

 勘違いしてそうな人は
 例えば
    Dim rng1 As Range
    Set rng1 = Cells(1, 1)
    Debug.Print ObjPtr(rng1)
    Set rng1 = Nothing          '←これでA1セルが消滅したらエラいこってす ^^;
    Debug.Print ObjPtr(rng1)

    Set rng1 = Cells(1, 1)
    Debug.Print ObjPtr(rng1)
    Cells(1, 1).Delete          '←Deleteしたからと言っても、
    Debug.Print ObjPtr(rng1)    '←ObjPtrの値はDelete前と変わらない
    Debug.Print rng1.Address    '←でも「実行時エラー'424':オブジェクトが必要です。」は発生する

 Nothingをセットする事とオブジェクト自身の状況は直接的に関係しない事がわかります。
 とか

 GDIでCreateCompatibleDCしたメモリデバイスコンテキストはLongPtr型変数に入れて操作します。
 Nothingの代わりにゼロを代入する事になる訳ですが、やってる事の意味はほぼ同じです。
 ゼロを代入した事によってメモリ上から解放されるって...イメージ湧きますかね?
 この場合でもやはり End Sub 直前にゼロを代入したくなるものでしょうかね?
 その前にDeleteObjectで明示的に破棄するの忘れてたら意味無いと思いません?

              ...とか、そういうお話を幾つか考えてみれば宜しいのかなと。そんな風に思いました。以上感想です

(白茶) 2023/12/01(金) 00:21:55


>コードの途中で解放ならまだわかるんですけど。
>いらないですよね!?
>ところで、ポインタってなんです?

(´・ω・`)さんが言っていることもありますね。
プロシージャが終了しても、エクセルが終了してなかったら、残る変数もありますね。
循環参照については、よくわかりませんが、そういうこともあるってことでしょう。
だったら、間違いを防ぐにはNothingを入れておけば良いってことじゃないでしょうか。

大方、どちらでも良いことかなと思っています。わたしはNothingを入れていません。
大きなオブジェクトを扱い、メモリが心配な場合には気をつけなければならないですが。

そうしてみると、コードを書く作法みたいなものかなと思います。
ただ、コードを書いていれば、どこでどのような失敗をするかも知れません。
とすれば、間違いが起こる可能性は極力排除したい。
そういう理由もあるかも知れません。

ポインタ (英: pointer) とは、コンピュータプログラミングにおいて、変数や定数、サブルーチン(関数)などが置かれたメインメモリ上の番地(メモリアドレス)を格納するための特殊な変数のこと。 あるオブジェクトがなんらかの論理的位置情報に基づいてアクセスできるとき、それを参照する(指し示す)ためのものである。 Wikipediaより

なので、VBAではポインタとは呼びませんが、オブジェクト変数というのは実質的にポインタです。
また、他の言語に慣れている人であれば、ポインタと言えば一発でわかるなんてこともあります。
(ゆたか) 2023/12/01(金) 09:04:01


 > のようなコードで、最後の「Set Dic = Nothing」って
 > 必要なんでしょうか?
 > 「End Sub」に行ったらオブジェクトは勝手に解放されると思ってたんですが・・。

 その理解でいいと思います。(「解放」と言う表現は既に指摘がある通りです)

 それで問題が起きるなら、Nothingを入れたって同じ問題が起きるハズです。
 違う経験をした人が居たらそれが何だか教えて欲しい。

 この話は過去に何度もやっていますが、毎回不完全燃焼気味となる。
 なぜなら、分かってない者同士がああでもない、こうでもないと言っているだけなので。

 Microsoftの人間でさえ、曖昧さが残る話をしている。
 (基本、プロシージャレベルの変数はSet Nothingは不要との立場ではあった)

 分かっている人なんて一人もいないのかも知れない。

 ゴミってなんですか?
 書くとゴミっが無くなり、書かないと残るんですか(どうやって確かめたのですか?)

 循環参照の話は分かりませんが、
 その観点からすると、Nothingにするにも順序を考えなければならないが、
 そんな順序を気にしてNothingを書いていますか。

 ※下手な順序でNothingを入れたら、本来、先にNothingすべきオブジェクトが
   Nothingに出来なくなりますけど、大丈夫?
   まぁ順序を気にしている人は立派と言わざるを得ないですが。

 > でも、そんなこと言ったら「てめ、電話切らずに帰っちゃうんかよwww」って事にもなるから
 > やはり最後にNothingセットするのが作法なんじゃない? とも考えられますよね ^^:
 電話の話ならそうでしょうが、車のアクセサリーなら、一個一個OFFにしません。エンジン切ればいいので。

(半平太) 2023/12/01(金) 11:48:34


 おお〜、いい例えですね。

 ...そういや昔はライトの消し忘れでバッテリーあがった車をよく見かけたもんです。
    考えてみたら最近の車はホント優秀なんですね。

(白茶) 2023/12/01(金) 12:50:20


>「解放」だとどうしてもメモリの解放と混同してしまう。

白茶様がおっしゃる通り「メモリの解放」と完全に勘違いしていました。
掲載していたサンプルコードも実行し、少し変更しながら色々テスト実行してみました。
感動しました(泣)
これからは、コメントに「切断」と入れるようにしてみます。

> ゴミってなんですか?
> 書くとゴミっが無くなり、書かないと残るんですか(どうやって確かめたのですか?)
先輩方に「ごみが残る?」「ごみの様なものが残る?」と言われた記憶があったので、
そのように理解していたのですが、
実際に確かめたわけではありません。確かめ方もわかりません。
ただ、先輩方のコメントには、「メモリの解放」と書いてあったりしたので、
Nothingを入れない事によって、メモリの一部を確保したままになり、
メモリの容量を圧迫するのかな…と勝手に理解しておりました。

循環参照の話も、実際に循環参照なのかどうかも分かりません。
先に掲載したように、曖昧だったので、Nothingをやらないよりはやった方が良い。
という程度の認識です。

掲示板を用意してくれた方、質問者の方、
多数の回答をしている方々のおかげで、大変勉強になりました。
ありがとうございます。

(匿名) 2023/12/02(土) 09:39:16



貴方は(うぃる)さんですか。
(?) 2023/12/02(土) 10:30:27

混乱させてしまい、申し訳ございません。
前に「匿名」という名前で回答付けた者ですが、
私の付けた回答に対して、誤りなどのご指摘を受けたので、
そのお礼として投稿いたしました。

(匿名) 2023/12/02(土) 10:36:21


 おはようございます。
 流行り病にかかってしまい、投稿できませんでした。

 みなさん、コメントありがとうございます。
 「オブジェクトの解放」、私も諸先輩方より教わってこのように長年コメントに記述してました。
 確かに「切断」とか「切り離す」とかの意味合いの方がしっくり来ますね。
 今後コードを作成するときに参考にします。
 (なんとなくスッキリしました)

 ゆたかさん
 ポインタ、について解説ありがとうございます。
 ちょっとまだ理解が追い付いてないですが、勉強していきます。

(うぃる) 2023/12/04(月) 08:54:34


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.