【问题标题】:Memory will not release in C# singleton modeC#单例模式下不会释放内存
【发布时间】:2021-07-19 23:38:50
【问题描述】:

我对单例模式在 C# 和 C++ 之间释放对象内存有疑问; 这里是 C++ 代码:

#include<iostream>
using namespace std;
class Rocket
{
private:
    Rocket() { speed = 100; }
    ~Rocket() {}
    static Rocket* ms_rocket;
public:
    int speed;
    static Rocket*ShareRocket()
    {
        if (ms_rocket == NULL)
            ms_rocket = new Rocket();
        return ms_rocket;
    }
    static void Close()
    {
        if (ms_rocket != NULL)
            delete ms_rocket;
    }
};
Rocket *Rocket::ms_rocket = NULL;
int main()
{
    Rocket* p =  Rocket::ShareRocket();
    p->speed = 100;
    cout << p->speed << endl;
    Rocket::Close();
    cout << p->speed << endl;
    getchar();
}

当我使用Rocket::Close()时,ms_rocket指向的内存空间会被释放,ms_rocket变成一个野指针,第二个“cout

    class A : IDisposable
    {
        public int age;
        public A() {  }
        public void Run()
        {
            Console.WriteLine("Run");
        }
        #region IDisposable Support
        private bool disposedValue = false; 

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    Console.WriteLine("A is release");
                }
                disposedValue = true;

            }
        }
        public void Dispose()
        {
            Dispose(true);
        }
        #endregion
    }

    class B
    {
        static A a;
        private B() { }
        public static A Intance
        {
            get
            {
                if (a == null)
                    a = new A();
                return a;
            }
        }

    }
    class Class1
    {

        public static void Main(string[] args)
        {
            A a = B.Intance;
            a.age =100;
            Console.WriteLine(a.age);
            a.Dispose();
            A a1 = B.Intance;
            Console.WriteLine(a1.age);
            Console.Read();
        }
    }

在C#中,我认为当我使用Dispose()时,内存(B单例中的'a'对象)会被释放,但是在第二次访问时,年龄值不应该是100,而静态变量'a ' 将变得像一个野指针。 谁能告诉我为什么?

【问题讨论】:

  • C# 有一个 garbage collector 可以在需要的时候删除东西,在 C++ 中,你是 garbage collector 并且你决定什么时候删除以及删除什么,所以基本上我猜在这种情况下 garbage collector 没有释放你正在谈论的内存。此外,在 C++ 中,如果您尝试将其打印出来,您也可能具有相同的值,但在这种情况下,它只是一个未定义的行为,而不是一些有效的东西。
  • Karen 所说的,但 C# 中的 GC 确实有一个方法,在第一次传递中它标记对象以进行垃圾回收。即使您致电GC.Collect,它也只会标记第一次传递的项目。在随后的传递中,它最终会为它释放内存。
  • 当您delete 时,您是在说:“我不再需要它并保证不再使用它。”如果你违背了诺言,那是你的责任。因为任何检查以确保您遵守诺言都会减慢遵守诺言的程序,而这都是正确编写的程序,所以 C++ 不需要检查。
  • @KarenMelikyan,@jzian,Dispose() 也不会发布任何内容。这样您就可以对非托管资源进行清理。根据您的示例,如果您希望 GarbageCollector 最终清理 A,则需要通过某种方式在 B 上将其设置为 null。IE,将设置器添加到您执行操作的 B.Instance 属性:B.Instance = null
  • 旁注:A generally better, thread-safe C++ Singleton。请注意完全没有newdelete。这偏离了问题的代码,因为一旦创建,只有程序退出才能销毁对象。另一方面,您不需要 dispose 方法。已经为您完成了。

标签: c# c++ singleton


【解决方案1】:

在C#中Dispose主要用于在不需要unmanaged resources时立即释放它们,而不是释放对象本身占用的内存-它由垃圾收集器处理,垃圾收集器将释放(当GC决定它时)需要运行)只有当它无法从所谓的 GC 根访问时(静态变量是 GC 根之一,因此B.Intance 将在堆中保存对A 的此实例的引用)。

首先要释放A 的当前实例占用的内存,您需要将B.Instance 设置为null(并等待GC 运行)。

CLR 中的 fundamentals of garbage collection 也很有用。

【讨论】:

  • C++ 注意:dispose 的工作由 C++ 中的RAII 处理。因为在 C++ 中,您确切知道对象何时被销毁(它超出范围,它的管理器超出范围,或者您调用 delete)并且它立即发生,您很少需要 dispose 函数。
猜你喜欢
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 1970-01-01
相关资源
最近更新 更多