none
托管内存泄露?!…… 垃圾回收失效?!…… RRS feed

  • 问题

  • 同志们,我发现了一个托管内存泄露的问题 而不是传统的非托管内存 见代码:
    // tempExe.cpp: 主项目文件。
    
    #include "stdafx.h"
    
    using namespace System;
    using namespace System::IO;
    
    ref class ClassB;
    public ref class ClassA
    {
    public:
    	StreamWriter^ w;
    	ClassB^ b;
    	ClassA(ClassB^ b_l)
    	{
    		b=b_l;
    		w= gcnew StreamWriter("xx.txt");
    	}
    	~ClassA()
    	{
    		w->WriteLine("Close ok!");
    		w->Close();
    	}
    };
    public ref class ClassB
    {
    public:
    	ClassA^ a;
    	ClassB()
    	{
    		a= gcnew ClassA(this);
    	}
    };
    public ref class ClassC
    {
    public:
    	StreamWriter^ w;
    	ClassC()
    	{
    		w= gcnew StreamWriter("xx.txt");
    	}
    	~ClassC()
    	{
    		w->WriteLine("Close ok!");
    		w->Close();
    	}
    };
    
    
    int main(array<System::String ^> ^args)
    {
        Console::WriteLine(L"Hello World");
    	ClassB^ b=gcnew ClassB();
    	Console::WriteLine("please put any thing");
    	Console::ReadLine();
    	delete b;
    	b=nullptr;
    	Console::WriteLine("stop pause");
    	Console::ReadLine();
        return 0;
    }
    
    

    (我是C++ c#们将就一下吧……)

    当我用c类(对照组)实验时 在第一次暂停时xx.txt无法正常访问 而当第二次暂停时 C类成功的释放,xx.txt中显示“close ok!! “
    是 当用B类实验时,由于A,B类互相持有,导致在第二次暂停时(B类的指针已经释放)XX.TXT文件依然无法访问,这说明A类还没有释放 并且在程序关闭后XX文件中也是为空白 没有“close ok!!”,A类释放失败,被强制关闭

    大家有什么好一点的解决方法么? 当然我知道在类中加几个成员函数可以达成 但是这是牵强并且容易忘记的…… 能结合垃圾回收吗?……


    • 已编辑 xqyww123 2011年12月24日 10:39
    • 已移动 ThankfulHeartModerator 2011年12月27日 6:34 C++问题(结合.NET) (发件人:.NET Framework 一般性问题讨论区)
    • 已移动 VisualEleven 2011年12月28日 1:50 (发件人:Visual C++)
    2011年12月24日 10:34

全部回复

  • 你的C++类都没实现IDisposable。析构函数在超出作用域时调用,finalizer可能在finalize线程调用(不确定会被调用),要这么写
    	~ClassA()
    	{
                   Dispose(true)
    	}
    
    	!ClassA()
    	{
                   Dispose(false);
            }
            void Dispose(bool disposing)
           {
                  if(disposing)
                  {
                         if(w!=nullptr) 
                         {
                              delete w;
                               w=null;
                         }
                  }
                  disposed=true;
           } 
           void Foo()
          {
              if (disposed)
                  throw gcnew ObjectDisposedException();
              //...
          }
    
    
    int main(array<System::String ^> ^args)
    {
            Console::WriteLine(L"Hello World");
            {
              	ClassA a;
                    A.Foo();
            }	
        return 0;
    }
    



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2011年12月28日 14:59
    版主
  • c++使用托管框架开发我不确定,我想原理上都是一样的,托管框架,托管的是内存管理,内存管理由一个独立的垃圾回收线程处理,既然是独立线程,你的线程和垃圾回收线程之间就不会是同步的,你希望看到同步的效果,就需要同步线程,你需要在你期待立刻看到垃圾回收效果的地方,进行同步,调用:

    GC.WaitForFullGCComplete();

    接下来,你可以看到,你期待释放的资源都已经释放好了。


    2011 c# mvp China. *George读起来像不像“饺子”?我爱吃饺子,我叫George。
    2011年12月29日 3:26
    版主
  • 你好,这不是C#,所以,我用外门汉来说,你显示实现了析构函数,那么CLR就会认为用户要自行处理而不是用默认的。然而,在你写的析构函数中,并没偶发现任何可以正确释放对象的代码。根据CLR中的原理,你的第一次是因为CLR要检查一下,第二次才被垃圾回收器回收了。我只是参与一下。呵呵呵。。。
    2012年1月3日 11:43