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.
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
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. –
VMMap podał zasadniczo te same informacje, został przydzielony jeden (lub więcej) duży blok. Nie pomaga w ustaleniu źródła wycieku. – Harriv
FastMM 4.90 ma funkcję "AllocateLargeBlock". Spróbowałbym umieścić tutaj warunkowy punkt przerwania na wystarczająco dużym rozmiarze. –