如何找到处置和内存问题? C#

时间:2021-10-11 04:07:29

My app was using 150mb of memory not to long ago, now it is at 286mb. It slowly rises so i must be forgetting to dispose something. This isnt much of a problem for me since i have 4gb but i want to send this to others who have only 1gb of ram. other then going through the code line by line how can i find objects that need to be disposed of or just generally large objects?

我的应用程序不久前使用的是150mb的内存,现在是286mb。它慢慢升起,所以我必须忘记丢弃一些东西。这对我来说不是一个问题,因为我有4gb,但我想把它发送给只有1gb内存的其他人。除了然后逐行完成代码我怎样才能找到需要处理的对象或者只是一般大的对象呢?

8 个解决方案

#1


Extending both JP and Reed's answers.

延伸JP和Reed的答案。

I wanted to clear up a bit of confusion. If you are seeing significant increases in memory the issue is unlikely to be a problem with calling Dispose. Dispose is typically used to free up unmanaged resources like handles. These don't take up much memory but instead are more precious as resources.

我想澄清一点混乱。如果您看到内存显着增加,则调用Dispose不会出现问题。 Dispose通常用于释放非托管资源,如句柄。这些不占用太多内存,而是作为资源更珍贵。

Increases in memory are generally associated with large objects or collections being accessible from a managed object being rooted directly or indirectly via a stack object or a strong GC handle. This is the area you will likely want to focus your investigation on.

内存的增加通常与可从直接或间接通过堆栈对象或强GC句柄间接生根的托管对象访问的大对象或集合相关联。这是您可能希望集中研究的领域。

#2


Check out the .NET Memory Profiler. There is a 15-day trial and it's well worth the license fee.

查看.NET Memory Profiler。有15天的试用版,非常值得许可费。

Easily identify memory leaks by collecting and comparing snapshots of .NET memory Snapshots include data about the .NET instance allocations and live instances at the time the snapshot was collected. They provide a lot of useful information and make it easy to identify potential memory leaks, especially when two snapshots are compared.

通过收集和比较.NET内存快照轻松识别内存泄漏快照包括有关收集快照时.NET实例分配和实时实例的数据。它们提供了大量有用的信息,可以轻松识别潜在的内存泄漏,尤其是在比较两个快照时。

#3


heres a method i use:

继承人我使用的方法:

http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx

#4


You can also use WinDbg and SOS. These have the advantage of being free and very, very thorough, if a bit tricky to get used to.

您还可以使用WinDbg和SOS。如果有点习惯,它们具有免费且非常彻底的优点。

Here's a blog post describing the process.

这是一篇描述该过程的博客文章。

#5


Code project currently has a link to an app specifically for finding undisposed objects.

代码项目目前有一个专门用于查找未处理对象的应用程序的链接。

http://www.codeproject.com/KB/dotnet/undisposed.aspx

#6


Check out this link

看看这个链接

Stephen Toub goes into great length to explain various techniques for doing this, Following are some brief highlights from his article

Stephen Toub竭尽全力解释这样做的各种技巧,以下是他的文章中的一些简短的亮点

  • By adding a finalizer for debugging purposes, you can introduce a way to find out when a class was not properly disposed,if the finalizer is never invoked, you know that disposed wasn't called

    通过添加终结器以进行调试,您可以介绍一种方法来找出何时没有正确处理类,如果从未调用终结器,您知道处理器未被调用

  • To get additional information about the instance, threadIds etc to aid in narrowing down which instance didn't have it's disposed invoked, he creates a FinalizationDebgger class which your disposable class would hold onto which wouldin turn call the Dispose of the FinalizationDebugger class instance when it itself is disposed. If Dispose isn't called on your class instance then when the Finalizer runs it will invoke the finalizer for FinalizationDebgger instance where in you could assert or throw an exception to help debug the problem,

    为了获得有关实例,threadIds等的更多信息以帮助缩小哪个实例没有调用它,他创建了一个FinalizationDebgger类,你的一次性类将保留在该类上,当它调用FinalizationDebugger类实例时,它将调用它的Dispose。本身被处置。如果没有在类实例上调用Dispose,那么当Finalizer运行时,它将调用FinalizationDebgger实例的终结器,您可以在其中断言或抛出异常以帮助调试问题,

  • Move all the tracking related code into a base class which your disposable class would then inherit from, which makes the code much cleaner. This approach may or may not work since your burn a base class and if you are inheriting from another base already.

    将所有跟踪相关的代码移动到您的一次性类将继承的基类中,这使代码更加清晰。这种方法可能会或可能不会起作用,因为您刻录了一个基类,并且您已经从另一个基类继承。

  • In the last option everything is factored out into a static class that your instances call into. The FinalizationDebugger becomes a static class that exposes three static methods: Constructor, Dispose, and Finalizer. The idea is that you call these methods from the appropriate place in your class(dispose/finalize/constructor).This is minimally invasive into your code, as it typically involves adding only three lines of code. All of these methods are marked with a ConditionalAttribute such that they'll only be called by your class when you compile your class in DEBUG mode.

    在最后一个选项中,所有内容都被分解为实例调用的静态类。 FinalizationDebugger成为一个静态类,它暴露了三个静态方法:Constructor,Dispose和Finalizer。这个想法是你从类中的适当位置调用这些方法(dispose / finalize / constructor)。这对你的代码来说是微创的,因为它通常只涉及三行代码。所有这些方法都用ConditionalAttribute标记,这样只有在DEBUG模式下编译类时才会被类调用。

Stephen also explains the pros and cons of each of his approaches. The solutions presents various options and you would need to evaluate each to figure out which one works best for your situation. A MUST read IMHO

斯蒂芬还解释了他的每一种方法的利弊。解决方案提供了各种选项,您需要对每个选项进行评估,以确定哪种方案最适合您的情况。必须阅读恕我直言

Hope this helps.

希望这可以帮助。

#7


Also try out ANTS Memory Profiler. There's a 14 day fully functional free trial, and I really like the UI.

还可以尝试ANTS Memory Profiler。这是一个为期14天的全功能免费试用版,我非常喜欢用户界面。

Disclosure: They sponsor Herding Code right now, which is why I tried it out. But I'm really impressed with it - I profiled an application for 30 hours and got tons of useful information out of it. The UI is really helpful - it guides you through the process, and it looks dang purty.

披露:他们现在赞助Herding Code,这就是我尝试的原因。但我对此印象非常深刻 - 我将应用程序描述了30个小时,并获得了大量有用的信息。用户界面非常有用 - 它会指导您完成整个过程,并且看起来像是真的。

alt text http://www.red-gate.com/products/ants_memory_profiler/images/object_retention_graph.gif

alt text http://www.red-gate.com/products/ants_memory_profiler/images/object_retention_graph.gif

#8


Here are couple of tricks using the ANTS Memory Profiler to help find undisposed objects and fix the leaks.

以下是使用ANTS Memory Profiler帮助查找未处理对象并修复泄漏的几个技巧。

  1. The ANTS Memory profiler allows a filter to be set that show just objects that contain a Dispose() method. Turn this on, and you'll be given a list of live objects that have not been disposed.

    ANTS内存分析器允许设置过滤器,只显示包含Dispose()方法的对象。打开它,您将获得一个尚未处置的活动对象列表。

  2. While finding undisposed objects is useful, even more useful is knowing why these objects are not being disposed. Finding where these undisposed objects are created goes a long way to finding the reason for the leak. If you are able to change the code of the leaking object, a useful trick is to introduce a field to hold a stacktrace, and populate this field at the time of object construction. Then because the ANTS memory profiler allows you to inspect fields of objects, you can simply read off the stacktrace as it was at the time the leaking objects were created. This will give you a strong clue as to who the owner of the leaking objects should be, and how they should go about calling Dispose on the objects they are responsible for.

    虽然找到未曝光的对象是有用的,但更有用的是知道为什么不处理这些对象。找到这些未曝光对象的创建位置对于找到泄漏原因还有很长的路要走。如果您能够更改泄漏对象的代码,一个有用的技巧是引入一个字段来保存堆栈跟踪,并在构造对象时填充此字段。然后,因为ANTS内存分析器允许您检查对象的字段,所以您可以简单地读取堆栈跟踪,就像创建泄漏对象时一样。这将为您提供一个强有力的线索,告知泄漏对象的所有者应该是谁,以及他们应该如何在他们负责的对象上调用Dispose。

#1


Extending both JP and Reed's answers.

延伸JP和Reed的答案。

I wanted to clear up a bit of confusion. If you are seeing significant increases in memory the issue is unlikely to be a problem with calling Dispose. Dispose is typically used to free up unmanaged resources like handles. These don't take up much memory but instead are more precious as resources.

我想澄清一点混乱。如果您看到内存显着增加,则调用Dispose不会出现问题。 Dispose通常用于释放非托管资源,如句柄。这些不占用太多内存,而是作为资源更珍贵。

Increases in memory are generally associated with large objects or collections being accessible from a managed object being rooted directly or indirectly via a stack object or a strong GC handle. This is the area you will likely want to focus your investigation on.

内存的增加通常与可从直接或间接通过堆栈对象或强GC句柄间接生根的托管对象访问的大对象或集合相关联。这是您可能希望集中研究的领域。

#2


Check out the .NET Memory Profiler. There is a 15-day trial and it's well worth the license fee.

查看.NET Memory Profiler。有15天的试用版,非常值得许可费。

Easily identify memory leaks by collecting and comparing snapshots of .NET memory Snapshots include data about the .NET instance allocations and live instances at the time the snapshot was collected. They provide a lot of useful information and make it easy to identify potential memory leaks, especially when two snapshots are compared.

通过收集和比较.NET内存快照轻松识别内存泄漏快照包括有关收集快照时.NET实例分配和实时实例的数据。它们提供了大量有用的信息,可以轻松识别潜在的内存泄漏,尤其是在比较两个快照时。

#3


heres a method i use:

继承人我使用的方法:

http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx

#4


You can also use WinDbg and SOS. These have the advantage of being free and very, very thorough, if a bit tricky to get used to.

您还可以使用WinDbg和SOS。如果有点习惯,它们具有免费且非常彻底的优点。

Here's a blog post describing the process.

这是一篇描述该过程的博客文章。

#5


Code project currently has a link to an app specifically for finding undisposed objects.

代码项目目前有一个专门用于查找未处理对象的应用程序的链接。

http://www.codeproject.com/KB/dotnet/undisposed.aspx

#6


Check out this link

看看这个链接

Stephen Toub goes into great length to explain various techniques for doing this, Following are some brief highlights from his article

Stephen Toub竭尽全力解释这样做的各种技巧,以下是他的文章中的一些简短的亮点

  • By adding a finalizer for debugging purposes, you can introduce a way to find out when a class was not properly disposed,if the finalizer is never invoked, you know that disposed wasn't called

    通过添加终结器以进行调试,您可以介绍一种方法来找出何时没有正确处理类,如果从未调用终结器,您知道处理器未被调用

  • To get additional information about the instance, threadIds etc to aid in narrowing down which instance didn't have it's disposed invoked, he creates a FinalizationDebgger class which your disposable class would hold onto which wouldin turn call the Dispose of the FinalizationDebugger class instance when it itself is disposed. If Dispose isn't called on your class instance then when the Finalizer runs it will invoke the finalizer for FinalizationDebgger instance where in you could assert or throw an exception to help debug the problem,

    为了获得有关实例,threadIds等的更多信息以帮助缩小哪个实例没有调用它,他创建了一个FinalizationDebgger类,你的一次性类将保留在该类上,当它调用FinalizationDebugger类实例时,它将调用它的Dispose。本身被处置。如果没有在类实例上调用Dispose,那么当Finalizer运行时,它将调用FinalizationDebgger实例的终结器,您可以在其中断言或抛出异常以帮助调试问题,

  • Move all the tracking related code into a base class which your disposable class would then inherit from, which makes the code much cleaner. This approach may or may not work since your burn a base class and if you are inheriting from another base already.

    将所有跟踪相关的代码移动到您的一次性类将继承的基类中,这使代码更加清晰。这种方法可能会或可能不会起作用,因为您刻录了一个基类,并且您已经从另一个基类继承。

  • In the last option everything is factored out into a static class that your instances call into. The FinalizationDebugger becomes a static class that exposes three static methods: Constructor, Dispose, and Finalizer. The idea is that you call these methods from the appropriate place in your class(dispose/finalize/constructor).This is minimally invasive into your code, as it typically involves adding only three lines of code. All of these methods are marked with a ConditionalAttribute such that they'll only be called by your class when you compile your class in DEBUG mode.

    在最后一个选项中,所有内容都被分解为实例调用的静态类。 FinalizationDebugger成为一个静态类,它暴露了三个静态方法:Constructor,Dispose和Finalizer。这个想法是你从类中的适当位置调用这些方法(dispose / finalize / constructor)。这对你的代码来说是微创的,因为它通常只涉及三行代码。所有这些方法都用ConditionalAttribute标记,这样只有在DEBUG模式下编译类时才会被类调用。

Stephen also explains the pros and cons of each of his approaches. The solutions presents various options and you would need to evaluate each to figure out which one works best for your situation. A MUST read IMHO

斯蒂芬还解释了他的每一种方法的利弊。解决方案提供了各种选项,您需要对每个选项进行评估,以确定哪种方案最适合您的情况。必须阅读恕我直言

Hope this helps.

希望这可以帮助。

#7


Also try out ANTS Memory Profiler. There's a 14 day fully functional free trial, and I really like the UI.

还可以尝试ANTS Memory Profiler。这是一个为期14天的全功能免费试用版,我非常喜欢用户界面。

Disclosure: They sponsor Herding Code right now, which is why I tried it out. But I'm really impressed with it - I profiled an application for 30 hours and got tons of useful information out of it. The UI is really helpful - it guides you through the process, and it looks dang purty.

披露:他们现在赞助Herding Code,这就是我尝试的原因。但我对此印象非常深刻 - 我将应用程序描述了30个小时,并获得了大量有用的信息。用户界面非常有用 - 它会指导您完成整个过程,并且看起来像是真的。

alt text http://www.red-gate.com/products/ants_memory_profiler/images/object_retention_graph.gif

alt text http://www.red-gate.com/products/ants_memory_profiler/images/object_retention_graph.gif

#8


Here are couple of tricks using the ANTS Memory Profiler to help find undisposed objects and fix the leaks.

以下是使用ANTS Memory Profiler帮助查找未处理对象并修复泄漏的几个技巧。

  1. The ANTS Memory profiler allows a filter to be set that show just objects that contain a Dispose() method. Turn this on, and you'll be given a list of live objects that have not been disposed.

    ANTS内存分析器允许设置过滤器,只显示包含Dispose()方法的对象。打开它,您将获得一个尚未处置的活动对象列表。

  2. While finding undisposed objects is useful, even more useful is knowing why these objects are not being disposed. Finding where these undisposed objects are created goes a long way to finding the reason for the leak. If you are able to change the code of the leaking object, a useful trick is to introduce a field to hold a stacktrace, and populate this field at the time of object construction. Then because the ANTS memory profiler allows you to inspect fields of objects, you can simply read off the stacktrace as it was at the time the leaking objects were created. This will give you a strong clue as to who the owner of the leaking objects should be, and how they should go about calling Dispose on the objects they are responsible for.

    虽然找到未曝光的对象是有用的,但更有用的是知道为什么不处理这些对象。找到这些未曝光对象的创建位置对于找到泄漏原因还有很长的路要走。如果您能够更改泄漏对象的代码,一个有用的技巧是引入一个字段来保存堆栈跟踪,并在构造对象时填充此字段。然后,因为ANTS内存分析器允许您检查对象的字段,所以您可以简单地读取堆栈跟踪,就像创建泄漏对象时一样。这将为您提供一个强有力的线索,告知泄漏对象的所有者应该是谁,以及他们应该如何在他们负责的对象上调用Dispose。