C# 下面的代码会导致内存泄漏吗?

C# 下面的代码会导致内存泄漏吗?,c#,memory-leaks,garbage-collection,C#,Memory Leaks,Garbage Collection,我想用C#创建一个内存泄漏,所以我编写了下面的代码来尝试创建一个。其概念是编写一个显式的Dispose,它只调用GC.SuppressFinalize()来阻止GC的工作。但是,当我运行代码时,内存似乎没有泄漏。有人能告诉我为什么吗 class Program { static void Main(string[] args) { while (true) { var t = new Foo(); t

我想用C#创建一个内存泄漏,所以我编写了下面的代码来尝试创建一个。其概念是编写一个显式的Dispose,它只调用GC.SuppressFinalize()来阻止GC的工作。但是,当我运行代码时,内存似乎没有泄漏。有人能告诉我为什么吗

class Program
{
    static void Main(string[] args)
    {
        while (true)
        {
            var t = new Foo();
            t.create_leak();
            t.Dispose();
        }
    }        
}
class Foo:IDisposable
{
    public void create_leak() {
        m_value = new int[10000];
        Console.WriteLine(m_value[10].ToString()+DateTime.Now.ToString());
    }

    public void Dispose() { GC.SuppressFinalize(this); }

    private int[] m_value;

    ~Foo() { }
}
其概念是编写一个显式的Dispose,它只调用GC.SuppressFinalize()来阻止GC的工作

GC.SuppressFinalize
不会阻止GC的工作。它只是防止GC调用对象上的终结器。但托管内存仍将被回收。如果要创建内存泄漏,则需要分配非托管内存或以无法回收的方式分配托管内存(因为它会无限期地被引用)。就是这样一种方式。编译的正则表达式是另一种(然而,一旦进程终止,内存当然仍将被回收)

其概念是编写一个显式的Dispose,它只调用GC.SuppressFinalize()来阻止GC的工作


GC.SuppressFinalize
不会阻止GC的工作。它只是防止GC调用对象上的终结器。但托管内存仍将被回收。如果要创建内存泄漏,则需要分配非托管内存或以无法回收的方式分配托管内存(因为它会无限期地被引用)。就是这样一种方式。编译的正则表达式是另一种(然而,一旦进程终止,内存当然仍会被回收)。

这不是泄漏,因为每个
Foo
在每个循环结束时仍有资格收集;
SuppressFinalize
只意味着不会调用
~Foo()
——它不会改变每个
m_值都有资格收集的事实


很难找到真正的漏洞。如果您只想填充内存,请将所有
Foo
实例保留在
列表中或类似的列表中,这样它们就永远无法被收集。对于真正的泄漏,您可能希望分配非托管内存—可能是
Marshal.AllocHGlobal

这不是泄漏,因为每个
Foo
在每个循环结束时仍有资格收集;
SuppressFinalize
只意味着不会调用
~Foo()
——它不会改变每个
m_值都有资格收集的事实


很难找到真正的漏洞。如果您只想填充内存,请将所有
Foo
实例保留在
列表中或类似的列表中,这样它们就永远无法被收集。对于真正的泄漏,您可能需要分配非托管内存—可能是
Marshal.AllocHGlobal

,我建议您使用诸如“位图”或“字体”之类的对象来生成内存泄漏。这些对象要求您显式地处理它,否则可能导致内存泄漏。可以在此处找到一个示例:


我建议您使用诸如“位图”或“字体”之类的对象来生成内存泄漏。这些对象要求您显式地处理它,否则可能导致内存泄漏。可以在此处找到一个示例:



我真的很难处理您的标题。。。“创建内存泄漏的正确方法”,这让我有点头晕actually@musefan,很高兴不仅仅是我!为什么要故意创建内存泄漏?我能想到的唯一原因是人们故意制造他们是为了黑客目的。@DavidArno这只是一个采访问题,不是为了黑客:)@musefan很抱歉,我已经更改了标题:)这样更好吗?我真的很难处理你的标题。。。“创建内存泄漏的正确方法”,这让我有点头晕actually@musefan,很高兴不仅仅是我!为什么要故意创建内存泄漏?我能想到的人们故意造成他们的唯一原因是出于黑客目的。@DavidArno这只是一个采访问题,不是为了黑客:)@musefan对不起,我已经更改了标题:)这样更好吗?GC从未调用过
Dispose
;它阻止GC调用
~Foo()
那么,
SuppressFinalize
不会阻止调用'Dispose',它会阻止Finalizer调用它。@Marc是的,我自己也注意到了。创建一个
Font
s的静态集合,然后把它们留在那里!一百万人应该这样做!。。。虽然从技术上讲,如果你在电脑上做的话,这不是内存泄漏purpose@musefan甚至不必是静态的,本地的就可以了。但这是否是一次泄漏还有争议——它只是耗尽了内存,而不是泄漏内存。GC从未调用过
Dispose
;它阻止GC调用
~Foo()
那么,
SuppressFinalize
不会阻止调用'Dispose',它会阻止Finalizer调用它。@Marc是的,我自己也注意到了。创建一个
Font
s的静态集合,然后把它们留在那里!一百万人应该这样做!。。。虽然从技术上讲,如果你在电脑上做的话,这不是内存泄漏purpose@musefan甚至不必是静态的,本地的就可以了。但这是否是一个泄漏还存在争议——它只是耗尽了内存,而不是泄漏。实际上,问题并不是内存泄漏:
Image
etc有终结器,最终托管组件和非托管组件都将正确释放。及时处理它们的原因是因为GC是不确定的,并且GDI句柄的数量非常有限:如果您等待GC释放它们,您可以耗尽可用的GDI池。实际上不是内存问题。从技术上讲,这些不是内存泄漏。它们会泄漏非内存资源(好吧,学究式的说,它们也会泄漏一些内存,但更直接的是,它们会泄漏非内存非托管资源:GDI+句柄)。@KonradRudolph,即使这样,它也不会泄漏