在.net中创建内存泄漏

时间:2023-01-20 17:31:28

The question Memory leak with java has been answered but is creating a memory leak possible in .net?

java中的内存泄漏问题已得到解答,但是在.net中可能会造成内存泄漏?

What would be an example?

会是什么样的例子?

5 个解决方案

#1


0  

for(int i = 0; i < 10; i++)
{
    IntPtr imageData = Marshal.AllocHGlobal(1024*1024);
}

This will result in 10 MB leaked memory for example. Everything unmanaged can leak, its hard to get something managed to leak memory, if at all.

例如,这将导致10 MB泄漏的内存。一切都不受管理可能会泄漏,如果有的话,很难设法泄漏内存。

#2


0  

As far as I see, you can "leak" memory by creating a separate AppDomain each time a specific operation is executed and forget to unload that AppDomain after the operation is finished. At least, they don't seem to be unloaded automatically: http://nikcodes.com/2013/01/18/understanding-appdomain-unloads-old-lessons-learned-anew/

据我所知,每次执行特定操作时都可以通过创建单独的AppDomain来“泄漏”内存,并且在操作完成后忘记卸载该AppDomain。至少,他们似乎没有自动卸载:http://nikcodes.com/2013/01/18/understanding-appdomain-unloads-old-lessons-learned-anew/

But one may argue this isn't a memory leak, because the AppDomains are stored internally and not "lost". However, I can't find a way to get all existing AppDomains and/or check if they are still in use to unload them. Plus, it can get quite nasty, depending on the size of Assemblies loaded into the AppDomain.

但有人可能会说这不是内存泄漏,因为AppDomains存储在内部而不是“丢失”。但是,我找不到获取所有现有AppDomain的方法和/或检查它们是否仍在使用以卸载它们。另外,它可能会非常讨厌,具体取决于加载到AppDomain中的程序集的大小。

Edit: You can list all AppDomains, but it is technically not in .Net: List AppDomains in Process so if you argue Marshal.AllocHGlobal(1024*1024); is a memory leak but not in .Net, then "unreferenced" AppDomains are a memory leak because the solution is not in .Net.

编辑:您可以列出所有AppDomains,但它在技术上不在.Net中:列出正在处理的AppDomains,所以如果你认为Marshal.AllocHGlobal(1024 * 1024);是内存泄漏但不是.Net,然后“未引用”AppDomains是内存泄漏,因为该解决方案不在.Net中。

; P

There are tons of philosophical discussions out there, whether unused references are to be called "resource leak" instead of "memory leak." For me, the AppDomain example might be a true memory leak, if there is no way of accessing the existing AppDomains.

那里有大量的哲学讨论,是否将未使用的引用称为“资源泄漏”而不是“内存泄漏”。对我来说,如果无法访问现有的AppDomain,AppDomain示例可能是真正的内存泄漏。

#3


0  

While not technically a leak, you can still observe the same symptoms (running out of memory) when you inadvertently keep references to objects you don't actually need any more. For instance if you have a static cache of previously computed data:

虽然技术上不是泄漏,但是当您无意中保留对实际上不再需要的对象的引用时,您仍然可以观察到相同的症状(内存不足)。例如,如果您有先前计算数据的静态缓存:

static List<string> previousResults = new List<string>();

public string GetSomeResult(int arg)
{
    string s = DoSomething(arg);
    previousResults.Add(s);
    return s;
}

Very stupid example, but it shows the point: When nobody ever clears the list, it will grow forever. I'm calling this a memory leak in .NET, even if it technically isn't one (as the objects are still addressable). There are more subtle ways of observing the same behavior where you don't see that you're still keeping references in the first place.

非常愚蠢的例子,但它表明了重点:当没有人清除列表时,它将永远增长。我在.NET中称这是一个内存泄漏,即使它在技术上不是一个(因为对象仍然是可寻址的)。有更多微妙的方法来观察相同的行为,你没有看到你仍然在第一时间保留引用。

#4


0  

The most common memory leak I see in .NET is a static object that never goes away. This is common for Singleton objects, but it can also be a mistake from a misunderstanding of how static objects work.

我在.NET中看到的最常见的内存泄漏是一个永远不会消失的静态对象。这对于Singleton对象很常见,但是对于静态对象如何工作的误解也可能是错误的。

Another, sneakier example of a memory leak is registering for a static event. For example, all of the events in the SystemEvents class are static. If an object registers itself for this event, it must de-register itself, or else the object will never be garbage collected.

内存泄漏的另一个偷偷摸摸的例子是注册静态事件。例如,SystemEvents类中的所有事件都是静态的。如果一个对象为此事件注册自己,它必须自行注销,否则该对象永远不会被垃圾回收。

We actually had that happen when someone registered a form to listen for the SystemEvents.SessionEnding event. These events are static. They hold on to a static list of delegates that are invoked when the event occurs. Even if the object is disposed, and all of your references to this object are set to null, the static event will continue to hold onto it, so the object will never be garbage collected. And since that object is preserved, all objects it references stay alive, too.

当有人注册表单来监听SystemEvents.SessionEnding事件时,我们确实发生了这种情况。这些事件是静态的。它们保留了在事件发生时调用的静态委托列表。即使放置了对象,并且对此对象的所有引用都设置为null,静态事件也将继续保留在该对象上,因此该对象永远不会被垃圾回收。并且由于该对象被保留,它引用的所有对象也保持活跃。

#5


0  

Here's a good way to create a true memory leak (objects inaccessible by running code but still stored in memory) in pure Java:

这是在纯Java中创建真正的内存泄漏(通过运行代码但仍然存储在内存中无法访问的对象)的好方法:

The application creates a long-running thread (or use a thread pool to leak even faster).

应用程序创建一个长时间运行的线程(或使用线程池来更快地泄漏)。

The thread loads a class via an (optionally custom) ClassLoader.

该线程通过(可选的自定义)ClassLoader加载一个类。

The class allocates a large chunk of memory (e.g. new byte[1000000]), stores a strong reference to it in a static field, and then stores a reference to itself in a ThreadLocal. Allocating the extra memory is optional (leaking the Class instance is enough), but it will make the leak work that much faster.

该类分配一大块内存(例如new byte [1000000]),在静态字段中存储对它的强引用,然后在ThreadLocal中存储对它自己的引用。分配额外的内存是可选的(泄漏Class实例就足够了),但它会使泄漏工作更快。

The thread clears all references to the custom class or the ClassLoader it was loaded from. Repeat.

该线程清除对自定义类或从中加载的ClassLoader的所有引用。重复。

Credit: https://*.com/a/6471947/6017500

#1


0  

for(int i = 0; i < 10; i++)
{
    IntPtr imageData = Marshal.AllocHGlobal(1024*1024);
}

This will result in 10 MB leaked memory for example. Everything unmanaged can leak, its hard to get something managed to leak memory, if at all.

例如,这将导致10 MB泄漏的内存。一切都不受管理可能会泄漏,如果有的话,很难设法泄漏内存。

#2


0  

As far as I see, you can "leak" memory by creating a separate AppDomain each time a specific operation is executed and forget to unload that AppDomain after the operation is finished. At least, they don't seem to be unloaded automatically: http://nikcodes.com/2013/01/18/understanding-appdomain-unloads-old-lessons-learned-anew/

据我所知,每次执行特定操作时都可以通过创建单独的AppDomain来“泄漏”内存,并且在操作完成后忘记卸载该AppDomain。至少,他们似乎没有自动卸载:http://nikcodes.com/2013/01/18/understanding-appdomain-unloads-old-lessons-learned-anew/

But one may argue this isn't a memory leak, because the AppDomains are stored internally and not "lost". However, I can't find a way to get all existing AppDomains and/or check if they are still in use to unload them. Plus, it can get quite nasty, depending on the size of Assemblies loaded into the AppDomain.

但有人可能会说这不是内存泄漏,因为AppDomains存储在内部而不是“丢失”。但是,我找不到获取所有现有AppDomain的方法和/或检查它们是否仍在使用以卸载它们。另外,它可能会非常讨厌,具体取决于加载到AppDomain中的程序集的大小。

Edit: You can list all AppDomains, but it is technically not in .Net: List AppDomains in Process so if you argue Marshal.AllocHGlobal(1024*1024); is a memory leak but not in .Net, then "unreferenced" AppDomains are a memory leak because the solution is not in .Net.

编辑:您可以列出所有AppDomains,但它在技术上不在.Net中:列出正在处理的AppDomains,所以如果你认为Marshal.AllocHGlobal(1024 * 1024);是内存泄漏但不是.Net,然后“未引用”AppDomains是内存泄漏,因为该解决方案不在.Net中。

; P

There are tons of philosophical discussions out there, whether unused references are to be called "resource leak" instead of "memory leak." For me, the AppDomain example might be a true memory leak, if there is no way of accessing the existing AppDomains.

那里有大量的哲学讨论,是否将未使用的引用称为“资源泄漏”而不是“内存泄漏”。对我来说,如果无法访问现有的AppDomain,AppDomain示例可能是真正的内存泄漏。

#3


0  

While not technically a leak, you can still observe the same symptoms (running out of memory) when you inadvertently keep references to objects you don't actually need any more. For instance if you have a static cache of previously computed data:

虽然技术上不是泄漏,但是当您无意中保留对实际上不再需要的对象的引用时,您仍然可以观察到相同的症状(内存不足)。例如,如果您有先前计算数据的静态缓存:

static List<string> previousResults = new List<string>();

public string GetSomeResult(int arg)
{
    string s = DoSomething(arg);
    previousResults.Add(s);
    return s;
}

Very stupid example, but it shows the point: When nobody ever clears the list, it will grow forever. I'm calling this a memory leak in .NET, even if it technically isn't one (as the objects are still addressable). There are more subtle ways of observing the same behavior where you don't see that you're still keeping references in the first place.

非常愚蠢的例子,但它表明了重点:当没有人清除列表时,它将永远增长。我在.NET中称这是一个内存泄漏,即使它在技术上不是一个(因为对象仍然是可寻址的)。有更多微妙的方法来观察相同的行为,你没有看到你仍然在第一时间保留引用。

#4


0  

The most common memory leak I see in .NET is a static object that never goes away. This is common for Singleton objects, but it can also be a mistake from a misunderstanding of how static objects work.

我在.NET中看到的最常见的内存泄漏是一个永远不会消失的静态对象。这对于Singleton对象很常见,但是对于静态对象如何工作的误解也可能是错误的。

Another, sneakier example of a memory leak is registering for a static event. For example, all of the events in the SystemEvents class are static. If an object registers itself for this event, it must de-register itself, or else the object will never be garbage collected.

内存泄漏的另一个偷偷摸摸的例子是注册静态事件。例如,SystemEvents类中的所有事件都是静态的。如果一个对象为此事件注册自己,它必须自行注销,否则该对象永远不会被垃圾回收。

We actually had that happen when someone registered a form to listen for the SystemEvents.SessionEnding event. These events are static. They hold on to a static list of delegates that are invoked when the event occurs. Even if the object is disposed, and all of your references to this object are set to null, the static event will continue to hold onto it, so the object will never be garbage collected. And since that object is preserved, all objects it references stay alive, too.

当有人注册表单来监听SystemEvents.SessionEnding事件时,我们确实发生了这种情况。这些事件是静态的。它们保留了在事件发生时调用的静态委托列表。即使放置了对象,并且对此对象的所有引用都设置为null,静态事件也将继续保留在该对象上,因此该对象永远不会被垃圾回收。并且由于该对象被保留,它引用的所有对象也保持活跃。

#5


0  

Here's a good way to create a true memory leak (objects inaccessible by running code but still stored in memory) in pure Java:

这是在纯Java中创建真正的内存泄漏(通过运行代码但仍然存储在内存中无法访问的对象)的好方法:

The application creates a long-running thread (or use a thread pool to leak even faster).

应用程序创建一个长时间运行的线程(或使用线程池来更快地泄漏)。

The thread loads a class via an (optionally custom) ClassLoader.

该线程通过(可选的自定义)ClassLoader加载一个类。

The class allocates a large chunk of memory (e.g. new byte[1000000]), stores a strong reference to it in a static field, and then stores a reference to itself in a ThreadLocal. Allocating the extra memory is optional (leaking the Class instance is enough), but it will make the leak work that much faster.

该类分配一大块内存(例如new byte [1000000]),在静态字段中存储对它的强引用,然后在ThreadLocal中存储对它自己的引用。分配额外的内存是可选的(泄漏Class实例就足够了),但它会使泄漏工作更快。

The thread clears all references to the custom class or the ClassLoader it was loaded from. Repeat.

该线程清除对自定义类或从中加载的ClassLoader的所有引用。重复。

Credit: https://*.com/a/6471947/6017500