Programing

.NET에서 메모리 누수를 찾는 데 유용한 전략과 도구는 무엇입니까?

lottogame 2020. 6. 13. 10:11
반응형

.NET에서 메모리 누수를 찾는 데 유용한 전략과 도구는 무엇입니까?


나는 10 년 동안 C ++을 썼다. 메모리 문제가 발생했지만 합리적인 노력으로 문제를 해결할 수 있습니다.

지난 몇 년 동안 저는 C #을 작성했습니다. 여전히 많은 메모리 문제가 발생합니다. 비결 정성으로 인해 진단 및 수정이 어렵고 C # 철학은 매우 확실하게 할 때 그러한 일에 대해 걱정할 필요가 없기 때문입니다.

내가 찾은 한 가지 특별한 문제는 코드에서 모든 것을 명시 적으로 처분하고 정리해야한다는 것입니다. 그렇지 않으면 메모리 프로파일 러가 실제로 도움이되지 않습니다. 내가 잘못 생각했는지, 내가 가진 도구가 최선이 아닌지 궁금합니다.

.NET에서 메모리 누수를 해결하는 데 유용한 전략과 도구는 무엇입니까?


메모리 누수가 의심되는 경우 Scitech의 MemProfiler를 사용 합니다.

지금까지는 매우 신뢰할 수 있고 강력하다는 것을 알았습니다. 적어도 한 번은 베이컨을 구했습니다.

GC는 .NET IMO에서 잘 작동하지만 다른 언어 또는 플랫폼과 마찬가지로 나쁜 코드를 작성하면 나쁜 일이 발생합니다.


잊어 버리기 어려운 문제에 대해서만 이 블로그 게시물에 설명 된 솔루션을 사용해보십시오 . 본질은 다음과 같습니다.

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif

우리는 프로젝트에서 Red Gate 소프트웨어의 Ants Profiler Pro사용 했습니다. 모든 .NET 언어 기반 응용 프로그램에서 실제로 잘 작동합니다.

.NET 가비지 콜렉터는 메모리 내 오브젝트를 정리할 때 매우 안전하다는 것을 알았습니다. 우리 는 나중에 언젠가 그것을 사용할 있기 때문에 객체를 보관할 것입니다. 이것은 우리가 메모리에서 부풀린 객체의 수에 대해 더주의를 기울여야한다는 것을 의미했습니다. 결국 메모리 오버 헤드를 줄이고 성능을 향상시키기 위해 모든 데이터 개체를 "주문형 요청"(필드가 요청되기 직전에)으로 변환했습니다.

편집 : 다음은 "요청시 팽창"의 의미에 대한 추가 설명입니다. 데이터베이스의 객체 모델에서 부모 객체의 속성을 사용하여 자식 객체를 노출시킵니다. 예를 들어, 다른 "상세"또는 "조회"레코드를 일대일 기준으로 참조한 레코드가있는 경우 다음과 같이 구성합니다.

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

위의 시스템은 메모리에 많은 레코드가있을 때 실제 메모리와 성능 문제를 일으킨다는 것을 발견했습니다. 그래서 우리는 객체가 요청되었을 때만 팽창하고 필요한 경우에만 데이터베이스 호출이 수행되는 시스템으로 전환했습니다.

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

개체가 필요할 때까지 메모리에 저장되지 않았기 때문에 훨씬 더 효율적인 것으로 나타났습니다 (Get 메서드에 액세스). 데이터베이스 적중을 제한하는 데있어 성능이 크게 향상되었으며 메모리 공간이 크게 향상되었습니다.


You still need to worry about memory when you are writing managed code unless your application is trivial. I will suggest two things: first, read CLR via C# because it will help you understand memory management in .NET. Second, learn to use a tool like CLRProfiler (Microsoft). This can give you an idea of what is causing your memory leak (e.g. you can take a look at your large object heap fragmentation)


Are you using unmanaged code? If you are not using unmanaged code, according to Microsoft, memory leaks in the traditional sense are not possible.

Memory used by an application may not be released however, so an application's memory allocation may grow throughout the life of the application.

From How to identify memory leaks in the common language runtime at Microsoft.com

A memory leak can occur in a .NET Framework application when you use unmanaged code as part of the application. This unmanaged code can leak memory, and the .NET Framework runtime cannot address that problem.

Additionally, a project may only appear to have a memory leak. This condition can occur if many large objects (such as DataTable objects) are declared and then added to a collection (such as a DataSet). The resources that these objects own may never be released, and the resources are left alive for the whole run of the program. This appears to be a leak, but actually it is just a symptom of the way that memory is being allocated in the program.

For dealing with this type of issue, you can implement IDisposable. If you want to see some of the strategies for dealing with memory management, I would suggest searching for IDisposable, XNA, memory management as game developers need to have more predictable garbage collection and so must force the GC to do its thing.

One common mistake is to not remove event handlers that subscribe to an object. An event handler subscription will prevent an object from being recycled. Also, take a look at the using statement which allows you to create a limited scope for a resource's lifetime.


This blog has some really wonderful walkthroughs using windbg and other tools to track down memory leaks of all types. Excellent reading to develop your skills.


I just had a memory leak in a windows service, that I fixed.

First, I tried MemProfiler. I found it really hard to use and not at all user friendly.

Then, I used JustTrace which is easier to use and gives you more details about the objects that are not disposed correctly.

It allowed me to solve the memory leak really easily.


If the leaks you are observing are due to a runaway cache implementation, this is a scenario where you might want to consider the use of WeakReference. This could help to ensure that memory is released when necessary.

However, IMHO it would be better to consider a bespoke solution - only you really know how long you need to keep the objects around, so designing appropriate housekeeping code for your situation is usually the best approach.


I prefer dotmemory from Jetbrains


Big guns - Debugging Tools for Windows

This is an amazing collection of tools. You can analyze both managed and unmanaged heaps with it and you can do it offline. This was very handy for debugging one of our ASP.NET applications that kept recycling due to memory overuse. I only had to create a full memory dump of living process running on production server, all analysis was done offline in WinDbg. (It turned out some developer was overusing in-memory Session storage.)

"If broken it is..." blog has very useful articles on the subject.


The best thing to keep in mind is to keep track of the references to your objects. It is very easy to end up with hanging references to objects that you don't care about anymore. If you are not going to use something anymore, get rid of it.

Get used to using a cache provider with sliding expirations, so that if something isn't referenced for a desired time window it is dereferenced and cleaned up. But if it is being accessed a lot it will say in memory.


One of the best tools is using the Debugging Tools for Windows, and taking a memory dump of the process using adplus, then use windbg and the sos plugin to analyze the process memory, threads, and call stacks.

You can use this method for identifying problems on servers too, after installing the tools, share the directory, then connect to the share from the server using (net use) and either take a crash or hang dump of the process.

Then analyze offline.


After one of my fixes for managed application I had the same thing, like how to verify that my application will not have the same memory leak after my next change, so I've wrote something like Object Release Verification framework, please take a look on the NuGet package ObjectReleaseVerification. You can find a sample here https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample, and information about this sample http://outcoldman.ru/en/blog/show/322


From Visual Studio 2015 consider to use out of the box Memory Usage diagnostic tool to collect and analyze memory usage data.

The Memory Usage tool lets you take one or more snapshots of the managed and native memory heap to help understand the memory usage impact of object types.

참고URL : https://stackoverflow.com/questions/134086/what-strategies-and-tools-are-useful-for-finding-memory-leaks-in-net

반응형