2014-10-03 3 views
0

파일의 일부 데이터 (예 : 1.00E + 7 개체)를 개체 목록으로 읽습니다. 그런 다음 각각을 변환하여 디스크에 직렬화하는 다른 클래스로 전달합니다. 이 과정에서 나는 상당한 메모리 누수가있다.C# GC가 루트가없는 개체를 수집하지 않습니다.

사용 !dumpheap -stat 나는 내 수업의 일부는 다음과 같은 메모리를 많이 차지하는 것을 볼 수 :

MT   count  TotalSize ClassName 
00185fd0 196180  7847200 Di3BMain.PeakDataClass 
0070d25c 392429  9418296 System.Collections.Generic.List`1[[DI3.Lambda`2[[System.Int32, mscorlib],[Di3BMain.PeakDataClass, Di3Main]], Di3]] 
00707038 392360  10986080 DI3.B`2[[System.Int32, mscorlib],[Di3BMain.PeakDataClass, Di3Main]] 
00930a0c 15453  12821476 CSharpTest.Net.Collections.BPlusTree`2+Element[[System.Int32, mscorlib],[DI3.B`2[[System.Int32, mscorlib],[Di3BMain.PeakDataClass, Di3Main]], Di3]][] 
7282fe8c 393241  13307220 System.Object[] 
72843a70  250 641899364 System.Int32[] 

이 번호가 같은 객체의 인스턴스가 생성되는 것이 분명 크기를 고려하면, 나는 예상대로 (하나의 입력 객체에 대해 하나의 출력 serializ 객체). 내 코드에서 예상대로 그러나 새로운 각 개체를 수집해야하는 매우 단순화 된 형식으로 된 다음과 같습니다 :

serializer.Add(new ConvertedObject(...){ ... }); 

내가 가장 큰 항목 중 일부의 뿌리를 확인하기 위해 노력 누출을 이해하기; 예를 들어 MT: 00707038을 사용하면 !gcroot -all 00707038; 하지만 그것은 나를주는 것은 Found 0 roots.

감안할 때 단지 모든 통계 전에 강제 것을 GC 내가 GC없이 뿌리와 그 큰 개체 중 하나를 수집하지 않는 이유를 궁금해, 다음 코드를 사용하여입니까?! 심지어 그것을 밀고 난 후에!

GC.Collect(); 
GC.SuppressFinalize(this); 
GC.WaitForPendingFinalizers(); 
+0

GC *가 (루트에서 액세스 할 수없는 경우) 개체를 수집 할 수 있기 때문에 즉시 그렇게해야한다는 것을 의미하지는 않습니다. 언제든지 개체를 수집 할 수 있습니다. 또한 코드를 표시하지 않았습니다. – Servy

+0

@Servy - he calss GC.Collect() –

+0

@HenkHolterman 기술적으로 이것은 콜렉션을 수행하기위한 요청 일뿐입니다. 하나는 GC가 원한다면 무시할 수 있습니다. 그럼에도 불구하고 문제는 재현 가능한 예가 부족합니다. 컬렉션을 수행 할 때 객체에 액세스 할 수 있습니다. – Servy

답변

3
  1. !gcroot -all 0070703800707038이 객체에 뿌리거나하지 않은 경우, 당신은 클래스의 인스턴스를 선택 싶어 찾으려면 .. [방법] 표에 대한 주소, 즉 사용하는 객체의 주소가 아닌 방법 테이블 주소. dumpheap -mt (no -stat)을 MT 주소와 함께 사용하면 지정된 클래스의 개체 목록을 덤프합니다 (목록이 길 경우 목록이 길어질 수 있으므로 결과를 제한하는 방법이나 몇 가지를 화면에 띄운 후 중단 할 수 있음)).

일단 개체 주소가 있으면 해당 주소로 gcroot을 실행하십시오.

  1. 반대쪽에서 개체가 루팅되지 않았기 때문에 GC가 수집하지 않는다는 것을 유의하십시오. 개체의 생성시기에 따라 gc는 주어진 세대에 대해 마지막으로 실행되었고, 덤프를 가져 왔을 때 루트가없는 객체가 덤프에 표시되는 것이 정상적 일 수 있습니다.

GC는 시스템이 메모리 부족에 있다고 생각하지 않는 한 모든 세대와 모든 개체를 수집하지 않을 수 있습니다.

+0

정확합니다.GC가 수집하도록 지시한다고해서 그것이 의미할만한 것은 아니며, 퍼포먼스와 비 결정적 행동을 위해 코드를 호출해서는 안됩니다! –

+0

감사합니다. 실제로 언급 한 요점을 놓치고있었습니다. 그러나 여전히 문제는 해결되지 않았고, 어떤 인스턴스에 대해서도'gcroot' 명령은'Error during command : IDebugClient가 구현되지 않은 인터페이스를 요구했습니다 .' 메시지를 제공합니다 ...! 왜 어떤 아이디어? – Hamed

+0

@Hamed 죄송합니다 .. 전 그 오류를 본 적이 없습니다. ** 내가 추측 할 수있는 것 **은 소리에서 디버거와 디버거 확장 버전간에 어떤 종류의 버전 불일치가있을 수 있습니다. . ** 1. ** windbg의 최신 버전 (windbg을 사용한다고 가정), ** 2 ** 및 sos.dll이 CLR/.Net 프레임 워크 버전에서로드되었는지 확인하십시오. 앱이 만들어졌습니다. 응용 프로그램을 실행하는 컴퓨터가 덤프를로드하는 컴퓨터와 약간의 버전 차이가있는 경우 오류를 이해하는 것이 어렵습니다. (희망 사항 : –

관련 문제