C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


■91530 / )  Re[6]: メモリリークに関して
□投稿者/ 魔界の仮面弁士 (2217回)-(2019/07/03(Wed) 19:37:39)
No91528 (kiku さん) に返信
> その結果をどのように掲示板に報告するのが良いのか
> ソースの内容を理解できていないため、
> わかりませんでした。

とりあえず、Compact か否かで結果が異なるという程度の理解でも可ということで。
Fx と CFx で結果が異なることを確認しておきたかっただけです。
(これも逆アセンブル扱いになるのだろうか…?)


.NET Framework の場合、Reference Source を見れば、
Form.Dispose(bool) が実装されていて、
その中で、ContainerControl.Dispose(bool) が呼ばれていることがわかります。
そしてそれが、Control.Dispose(bool) を呼び出していることも。
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Form.cs,3793


一方 .NET Comapct Framwork の場合、ソースコードは提供されていませんが、
No91525 の実験結果から、Form.Dispose(bool) は特に存在しておらず、
直接 Control.Dispose(bool) がそのまま呼ばれていることが確認できました。



No91529 (魔界の仮面弁士) に追記
> あと、経験則的なところで言えば、.NET Compact Framework 環境の場合、
> オブジェクトの使用後は、参照変数に Nothing 代入を積極的に行った方が良いみたいです。

Nothing の代入有無で、本当に解放状況が変化するかどうかを確認してみました。


端末を再起動して、空きメモリが十分に確保されている状態において、
Button1 でモードレス フォームを表示させた後、
Button2 でそれを Close させています。

すると、Close 直後の ★の行の Nothing 代入がコメントアウトされていた場合、
Form2 および LabelEx が直ちに Dispose されないケースが確認できました。

しかし Nothing 代入するようにした場合は、Button2 の時点ですぐに Dispose されるようになりました。


Partial Public Class Form1
  Inherits Form

  Private f As Form2 = Nothing

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    f = New Form2()
    f.Show()
  End Sub

  Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    If f IsNot Nothing AndAlso Not f.IsDisposed Then
      f.Close()
      'f.Dispose()

      'f = Nothing  '★
    End If
  End Sub
End Class

Public NotInheritable Class LabelEx
  Inherits Label
  Public ReadOnly Id As Long
  Public Sub New()
    Id = Now.Ticks
    Trace.WriteLine(String.Format("==> {0} 生成 {1}", MyClass.GetType().Name, Id))
  End Sub
  Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    MyBase.Dispose(disposing)
    Trace.WriteLine(String.Format("<== {0} 破棄 {1} ({2})", MyClass.GetType().Name, Id, disposing))
  End Sub
End Class

Partial Public Class Form2
  Inherits Form
  Public ReadOnly Id As Long
  Public Sub New()
    Id = Now.Ticks
    InitializeComponent()
    Trace.WriteLine(String.Format("==> {0} 生成 {1}", MyClass.GetType().Name, Id))
  End Sub
  Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)
    Controls.Add(New LabelEx() With {.Text = .Id.ToString()})
    SendToBack()
  End Sub
  Private Sub Form2_Disposed(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Disposed
    Trace.WriteLine(String.Format("<== {0} 破棄 {1}", MyClass.GetType().Name, Id))
  End Sub
  Protected Overrides Sub OnDoubleClick(ByVal e As System.EventArgs)
    MyBase.OnDoubleClick(e)
    Close()
  End Sub
End Class



ただ、何度も実験を繰り返すと空きメモリが減ってくるようで、
その場合はどうやら GC が発動するらしく、Nothing 代入せずとも
Dispose される結果になるようです。
返信 編集キー/


管理者用

- Child Tree -