7

Mam dziwny problem z moją aplikacją, jego użycie pamięci rośnie o kilkaset megabajtów naraz, co jakiś czas i ostatecznie aplikacja zamiera. Aplikacja napisana jest z Delphi, wykorzystuje bazę danych, COM (dla OPC) i TCP/IP.Przeciek pamięci z Delphi/DBExpress

Dzięki FastMM śledzę zrzut ekranu zużycia pamięci. Nie jestem całkowicie pewien, jak czytać ten stół, ale wygląda na to, że coś przydzieliło 296463552 bajtów (0x100fb000, czy to "magiczna liczba"?) Trzy razy.

memory usage

Jakieś pomysły? Czy istnieje sposób śledzenia przydziałów pamięci innych niż Delphi-MM?

Używam Delphi 2007 z FastMM 4.96.

Edit:

napisałem małą klasę pomocnika przy użyciu IMallocSpy śledzić alokacji pamięci COM. Oto fragment z tego, co otrzymałem:

00119023 5:52:27.484 [4496] TCOMAllocSpy.PreRealloc size: 269462304 
00119024 5:52:27.734 [4496] (0002760C){ntdll.dll } [7C82860C] KiFastSystemCallRet + $0 
00119025 5:52:27.734 [4496] (0009F83A){MyApp.exe} [004A083A] JclDebug.JclCreateThreadStackTrace (Line 3943, "JclDebug.pas" + 7) + $1E 
00119026 5:52:27.734 [4496] (003D496A){MyApp.exe} [007D596A] ComLeakHelper.TCOMAllocSpy.DebugStack (Line 46, "ComLeakHelper.pas" + 2) + $9 
00119027 5:52:27.734 [4496] (003D4B52){MyApp.exe} [007D5B52] ComLeakHelper.TCOMAllocSpy.PreRealloc (Line 125, "ComLeakHelper.pas" + 4) + $2 
00119028 5:52:27.734 [4496] (000053B6){MyApp.exe} [004063B6] [email protected] (Line 14090, "sys\system.pas" + 10) + $0 
00119029 5:52:27.734 [4496] (002E4490){MyApp.exe} [006E5490] DBXCommon.TDBXCommand.SetText (Line 5304, "..\..\..\..\..\src\pas\dbx\driver\DBXCommon.pas" + 13) + $5 
00119030 5:52:27.734 [4496] (0010A340){MyApp.exe} [0050B340] WideStrings.TWideStrings.GetValue (Line 580, "common\WideStrings.pas" + 3) + $D 
00119031 5:52:27.734 [4496] (002E1AFC){MyApp.exe} [006E2AFC] DBXCommon.TDBXProperties.GetValue (Line 4046, "..\..\..\..\..\src\pas\dbx\driver\DBXCommon.pas" + 1) + $7 
00119032 5:52:27.734 [4496] (002E3FC9){MyApp.exe} [006E4FC9] DBXCommon.TDBXConnectionEx.GetProductName (Line 5071, "..\..\..\..\..\src\pas\dbx\driver\DBXCommon.pas" + 1) + $E 
00119033 5:52:27.734 [4496] (003765FA){MyApp.exe} [007775FA] SqlExpr.TSQLConnection.DoConnect (Line 2467, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 66) + $21 
00119034 5:52:27.734 [4496] (0011876D){MyApp.exe} [0051976D] DB.TCustomConnection.SetConnected (Line 2628, "DB.pas" + 8) + $4 
00119035 5:52:27.734 [4496] (00118728){MyApp.exe} [00519728] DB.TCustomConnection.Open (Line 2611, "DB.pas" + 0) + $4 
00119036 5:52:27.734 [4496] (00375D6F){MyApp.exe} [00776D6F] SqlExpr.TSQLConnection.CheckConnection (Line 2302, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 4) + $2 
00119037 5:52:27.734 [4496] (00379241){MyApp.exe} [0077A241] SqlExpr.TCustomSQLDataSet.CheckConnection (Line 3955, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 2) + $2 
00119038 5:52:27.734 [4496] (0037968A){MyApp.exe} [0077A68A] SqlExpr.TCustomSQLDataSet.OpenCursor (Line 4045, "..\..\..\..\..\src\pas\dbx\vcl\SqlExpr.pas" + 3) + $4 
00119039 5:52:27.734 [4496] (00125EA9){MyApp.exe} [00526EA9] DB.TDataSet.SetActive (Line 9245, "DB.pas" + 12) + $7 
00119040 5:52:27.734 [4496] (00125CA1){MyApp.exe} [00526CA1] DB.TDataSet.Open (Line 9201, "DB.pas" + 1) + $6 
... 

Problem pojawia się w związku z połączeniem z bazą danych. Używam sterowników Firebird 2.1, DBExpress i InterXpress for Firebird z Upscene.

Edit2: Wydaje się to analizować podobny problem, przynajmniej Koncentruje się na takich samych zasadach jak tutaj: http://www.yac.com.pl/mt.texts.sqlexpr-2.en.html

+0

Możesz spróbować, jeśli VMMap od sysinternals daje więcej informacji, ale jeden pewny sposób śledzenia to byłoby użycie procdump (z sysinternals). Niech automatycznie utworzy plik zrzutu po przekroczeniu limitu pamięci i przeanalizuje zrzut za pomocą WinDbg. –

+0

VMMap podał zasadniczo te same informacje, został przydzielony jeden (lub więcej) duży blok. Nie pomaga w ustaleniu źródła wycieku. – Harriv

+0

FastMM 4.90 ma funkcję "AllocateLargeBlock". Spróbowałbym umieścić tutaj warunkowy punkt przerwania na wystarczająco dużym rozmiarze. –

Odpowiedz

1

Gdy aplikacja jest zamrożona, twój może spróbować spojrzeć na stosie, aby dowiedzieć się, dlaczego go zamraża: http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer

można spróbować memproof prześledzić całą alokację zasobów (i ich stackTrace): http://www.torry.net/tools/debug/memory/memp0948.zip

+0

Próbowałem utworzyć podobne alokacje pamięci za pomocą CoTaskMemAlloc (która działała), ale funkcja memproof nie może ich śledzić. – Harriv

0

spróbuj EurekaLog do zlokalizowania problem.

+0

Zobacz mój komentarz do André, to samo odnosi się do EurekaLog, jak również do wbudowanego wykrywania FastMM, ponieważ alokacja pamięci nie odbywa się za pośrednictwem menedżera pamięci Delphi (= FastMM). – Harriv

+0

I tak, używam EurekaLog :) – Harriv