![]() |
Speicherproblem mit Objekten in DLL
Hallo zusammen,
ich habe ein Problem mit dem Freigeben von Objekten in einer DLL. Ich Rufe eine Funktion zum Erzeugen eines Objekts aus einem nach JSON serialisierten String auf. Dann wird das Objekt verwendet und schlussendlich mit FreeAndNil wieder frei gegeben. Alle generischen Listen, die Teil der Klasse sind, werden im Destruktor ordnungsgemäß freigegeben (also erst die Objekte in den TList<TIrgendeinObjekt> Elementen und abschließend die Listen selber. Wenn ich den Constructor und den Destructor in einer Testanwendung (normale Win32 exe) zyklisch aufrufe und genau das selbe Objekt aus den serialisierten Daten erzeuge, wird der Speicher von der Anwendung einmalig allokiert, von Windows reserviert und entsprechend immer wieder verwendet. Das heißt, der Speicherbedarf der Anwendung steigt dauerhaft um ca 2-3MB. Es handelt sich um ein größeres Objekt mit längerem Tracelog, daher die Größe. Wenn ich nun die gleiche Klasse in eine Win32 dll verfrachte und das Objekt dort instanziere und wieder freigebe, steigt der Speicherverbrauch bei jedem Aufruf aufs neue an. D.h. mit jedem neuen Durchlauf des Konstruktors schnappt sich die Anwendung zusätzliche 2-5MB. Wie kann ich dieses Verhalten erklären - und noch viel wichtigter - wie kann ich es abstellen :roll: Viele Grüße Bastian |
AW: Speicherproblem mit Objekten in DLL
Wird Shared Memory verwendet?
Erstellen, Verwenden und Freigeben im selben Modul (EXE/DLL) oder wird da etwas zwischen EXE und DLL übergeben? |
AW: Speicherproblem mit Objekten in DLL
Ja SharedMem habe ich als erste Unit in den Uses der DPR mit drin (habe es auch ohne versucht)
Der Aufruf des Objekts ist wie folgt: - dpr Datei beinhaltet die eigentlich Unit (mit Form) - die "Unit mit Form" wird in einem TThread.execute gestartet bzw. mit CreateForm erzeugt - die TThread.execute Ereignis wird laut Breakpoint nur einmalig durchlaufen - in der "Unit mit Form" wird das Objekt in einer Funktion (Abarbeitung der Anfrage von ausserhalb der DLL instanziert, verwendet und wieder freigegeben) - Das eigentliche Objekt steckt in seiner eigenen Unit, die die ganze Klasse enthält - von der aufrufenden Anwendug wird ein Record an die DLL übergeben. Der Record ist eine definierte Schnittstelle der aufrufenden Anwendug. Es handelt sich um eine Integration in einen FTP Server, der die relevanten Daten an die DLL übergibt (FTP Benutzernamen, übertragene Datei, Operation, ...) Immer wenn eine Datei übertragen wird, wird der Inhalt dem FTP Benutzer zugeordnet und der Inhalt der Datei mit der eigentlichen Anforderung ausgewertet. Ich hoffe ich habe das verständlich aufgelistet :wink: |
AW: Speicherproblem mit Objekten in DLL
Die entscheidende Frage ist doch:
Wird der Destruktor in der DLL durchlaufen, sprich kommst du an einem Haltepunkt darin an? Wenn Hostanwendung und DLL in der gleichen Projektgruppe liegen, solltest du direkt in der DLL debuggen können, sofern Debuginformationen und ggf. externe Debugsymbole aktiviert sind. Ansonsten kannst du die Hostanwendung auch als solche im DLL-Projekt eintragen und dieses dann starten. Wichtig ist dabei, dass Speicher nicht unbedingt sofort wieder freigegeben wird. Zur Optimierung behält der Speichermanager den Speicher ggf. auch, um ihn später erneut zu verwenden. Deshalb kann man am Speicherverbrauch nicht unmittelbar sehen, ob der Speicher freigegeben wird. In den Beispielen zu FastMM4 z.B. ist ein Beispiel enthalten, wie man die Speicherbelegung direkt sehen kann. Außerdem zeigt es Speicherlecks beim Beenden an. Das funktioniert in einfacher Form auch mit ReportMemoryLeaksOnShutdown, das in Delphi bereits integriert ist. Bezüglich des Records: Ich persönlich würde die Klasse in der DLL (oder eine zusätzliche Verwaltungsklasse) einfach mit Implementierung eines Interfaces implementieren, das dann von der Hostanwendung abgerufen werden kann. Dann kann man die Klasse dort direkt nutzen. Dafür kannst du z.B. mein AppCentral Projekt nutzen: ![]() |
AW: Speicherproblem mit Objekten in DLL
Die DLL wird zu dem Zeitpunkt nicht beendet.
D.h. der Destruktor wird auch noch nicht durchlaufen. Die DLL läuft in der Anwendung über mehrere Tage/Wochen. FastMM4 habe ich in die DLL eingehängt und bekomme beim Beendern aber nur ein Speicherleck von ein paar kB. Das Problem ist aber, dass obwohl das Objekt zur Laufzeit instanziert und Freigegeben wird, die DLL den Speicher immer aufaddiert und nichts mehr davon freigibt. D.h. nach ein paar Iterationen belegt die DLL ihre vollen 2GB Speicher. Wie gesagt funktionieren die gleichen Aufrufe zum Erstellen und Freigeben des Objekts in einer Testanbwendung wie erwartet. |
AW: Speicherproblem mit Objekten in DLL
Fang mal von vorne an und mache dir ein ganz kleines Konsolenprogramm (kein VCL!) und rufe von dort die exportierte DLL-Funktion auf.
|
AW: Speicherproblem mit Objekten in DLL
Ja ich glaube da werde ich nicht drum rum kommen...
Ich werde berichten |
AW: Speicherproblem mit Objekten in DLL
Du übergibst der Dll Funktion den String? Um Spass mit langen Strings zu vermeiden verwende ich für die Kommunikation mit Dll's Named Pipes oder gleich einen Netzwerk Socket.
|
AW: Speicherproblem mit Objekten in DLL
Zitat:
Zitat:
Zitat:
|
AW: Speicherproblem mit Objekten in DLL
Oh, das war ein Missverständnis.
Der Destruktor der Klasse, der das Objekt freigibt wird natürlich durchlaufen. Nur die DLL wird nicht freigegeben (kein PROCESS_DETACH) Also Objekt auf (create) - verwenden - Objekt zu (freeandnil) Der Klassendestruktor wird auch durchlaufen und die enthaltenen TList Objekte werden korrekt freigegeben. Ich habe jetzt noch etwas weiter recherchiert und habe gesehen, dass es mit der Objektdeserialisierung zusammenhängen muss. FastMM4 zeigt mir unzählige Elemente an die noch offen sind, wenn die Anwendung beendet wird (obwohl die Objekte freigegeben sind). Erschwerend kommt hinzu, dass diese Aufrufe innerhalb eines TThreads erfolgen. Eventuell gibt es auch hier Probleme mit der Speicherverwaltung / Freigabe. Ich habe eine Test DLL gebaut, wo nur eine Funktion exportiert wird, die genau die gleiche Funktionalität abbildet wie oben beschrieben (Objekt auf, verwenden, zu) Da tritt dieses Speicherleck nicht auf. |
AW: Speicherproblem mit Objekten in DLL
Zitat:
Code:
Das ist soweit aber iO. Die Daten aus dem Objekt werden nur innerhalb der DLL verwendet, also nicht an die Hostanwendung durchgereicht.
RFTPEventStr = Record
// event info Event: Longword; // event code SubEvent: Longword; // sub-event code // user info SessionID: Longword; // unique ID of the FTP session User: array [0 .. 39] of AnsiChar; // user name ClientIP: array [0 .. 15] of AnsiChar; // IP number of client LocalIP: array [0 .. 15] of AnsiChar; // IP number the client connected to // event attributes Duration: Longword; // duration of events (in seconds) Size: Longword; // size of object (i.e. file) // hook info hWindow: word; // window handle to post decision to Message: longint; // message to post pReplyText: PAnsiChar; // pointer to text to send to user AuxOne: array [0 .. 511] of AnsiChar; // auxiliary area one AuxTwo: array [0 .. 511] of AnsiChar; // auxiliary area two end; |
AW: Speicherproblem mit Objekten in DLL
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal noch ein Bild von dem Problem im Anhang.
Ich verwende die ganzen TJsonArray, TJSonPair usw alle nur indirekt. Ich erzeuge mir mein Delphiobjekt über die integrierten Funktionen:
Code:
js ist der String mit dem nach JSON serialisierten Delphi Objekt.
result := TJson.JsonToObject<TMyObject>(js);
Die Funktion TJson.JsonToObject ist aus der REST.Json unit |
AW: Speicherproblem mit Objekten in DLL
Wenn ich die Meldungen richtig interpretiere, leakt nicht mein Objekt den Speicher, sondern das Deserialisieren des JSON Strings in das entsprechende Objekt...
|
AW: Speicherproblem mit Objekten in DLL
Das leakt auch wenn nur in der Exe aufgerufen? Wenn nicht, würde mich wundern wenn ein anderes Verhalten für Dll implementiert worden wäre. (wie auch immer das gehen sollte)
Zitat:
Ich kann mit einem Modul alle beliebigen Daten übertragen die ich will. Eine serialisierbare Memtable kümmert sich intern um alles nötige zur Datenverwaltung. Einmal eingebunden kann ich mit allen Modulen kommunizieren. Egal ob auf einem Rechner, zwischen Diensten, zwischen Rechnern, übers Internet. Selbst broadcast. |
AW: Speicherproblem mit Objekten in DLL
Die Andere Art der Datenübergabe in eine DLL ist sicher eine gute Idee, leider sind mir hier die Hände gebunden.
Ich konnte das Problem jetzt in der Tat auch rein in der Exe nachstellen. Keine Ahnung warum sich das Verhalten seither nicht ebenso in der Exe gezeigt hat. Aber umso besser. Das macht es nun leichter zu debuggen und einzuschätzen (hoffentlich). Nach einem Durchlauf mit einem Speicherleck von ein paar MB schreibt FastMM4 mir nun schon eine 100MB große Eventlog Datei :shock: Später dazu mehr |
AW: Speicherproblem mit Objekten in DLL
Hier mal ein paar Elemente aus dem Eventlog:
Code:
--------------------------------2023/12/6 18:41:38--------------------------------
A memory block has been leaked. The size is: 20 This block was allocated by thread 0x32A4, and the stack trace (return addresses) at the time was: CD781E [System.pas][System][@GetMem$qqri][4949] F38C6A [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3405] F38E96 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3454] F377FB [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3689] F38993 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3622] F38E23 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3438] F3763F [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3648] F3897A [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3615] F39F26 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.Marshal][3179] F3EF33 [REST.Json.pas][REST.Json][Json.TJson.ObjectToJsonValue][202] F3EF8D [REST.Json.pas][REST.Json][Json.TJson.ObjectToJsonObject][214] The block is currently used for an object of class: TJSONString The allocation number is: 700365 Current memory dump of 256 bytes starting at pointer address 9458460: A8 28 F0 00 01 00 00 00 BC DE 4A 07 00 00 00 00 00 00 00 00 4C 57 3E E0 00 00 00 00 E0 18 45 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 CB AF 0A 00 1E 78 CD 00 6A 8C F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 26 9F F3 00 33 EF F3 00 8D EF F3 00 A4 32 00 00 A4 32 00 00 3A 78 CD 00 4B 1D CE 00 47 E8 CD 00 0B 01 CE 00 13 40 F3 00 68 41 F3 00 DF FD F2 00 2E CB F2 00 73 C7 F2 00 50 FD F2 00 2E CB F2 00 14 00 00 00 74 46 74 01 51 A9 C1 1F A8 28 F0 00 01 00 00 00 5C 88 0A 09 00 00 00 00 00 00 00 00 AE 56 3E E0 00 00 00 00 E0 18 45 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 C9 AF 0A 00 1E 78 CD 00 6A 8C F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 26 9F F3 00 33 EF F3 00 8D EF F3 00 ¨ ( ð . . . . . ¼ Þ J . . . . . . . . . L W > à . . . . à . E . . . . . . . . . x Ï Î . . . . . Ë ¯ . . . x Í . j Œ ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó . & Ÿ ó . 3 ï ó . ï ó . ¤ 2 . . ¤ 2 . . : x Í . K . Î . G è Í . . . Î . . @ ó . h A ó . ß ý ò . . Ë ò . s Ç ò . P ý ò . . Ë ò . . . . . t F t . Q © Á . ¨ ( ð . . . . . \ ˆ . . . . . . . . . . ® V > à . . . . à . E . . . . . . . . . x Ï Î . . . . . É ¯ . . . x Í . j Œ ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó . & Ÿ ó . 3 ï ó . ï ó .
Code:
--------------------------------2023/12/6 18:41:39--------------------------------
A memory block has been leaked. The size is: 180 This block was allocated by thread 0x32A4, and the stack trace (return addresses) at the time was: CD781E [System.pas][System][@GetMem$qqri][4949] F0BF0C [System.JSON.pas][System.JSON][Json.TJSONValue.ParseString][2089] The block is currently used for an object of class: UnicodeString The allocation number is: 109337 Current memory dump of 256 bytes starting at pointer address 90A7E50: B0 04 02 00 01 00 00 00 4E 00 00 00 32 00 30 00 32 00 33 00 2D 00 31 00 32 00 2D 00 30 00 36 00 20 00 31 00 38 00 3A 00 34 00 30 00 3A 00 34 00 35 00 3A 00 20 00 53 00 65 00 74 00 20 00 54 00 61 00 73 00 6B 00 20 00 53 00 65 00 74 00 75 00 70 00 20 00 54 00 69 00 6D 00 65 00 20 00 28 00 55 00 54 00 43 00 29 00 20 00 32 00 30 00 32 00 33 00 2D 00 31 00 32 00 2D 00 30 00 36 00 20 00 31 00 37 00 3A 00 34 00 30 00 3A 00 34 00 35 00 20 00 55 00 54 00 43 00 20 00 28 00 36 00 30 00 6D 00 69 00 6E 00 29 00 00 00 26 9D 66 F4 79 01 84 5F 79 01 84 5F 79 01 00 00 00 00 70 72 0A 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 1B AB 01 00 1E 78 CD 00 0C BF F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ° . . . . . . . N . . . 2 . 0 . 2 . 3 . - . 1 . 2 . - . 0 . 6 . . 1 . 8 . : . 4 . 0 . : . 4 . 5 . : . . S . e . t . . T . a . s . k . . S . e . t . u . p . . T . i . m . e . . ( . U . T . C . ) . . 2 . 0 . 2 . 3 . - . 1 . 2 . - . 0 . 6 . . 1 . 7 . : . 4 . 0 . : . 4 . 5 . . U . T . C . . ( . 6 . 0 . m . i . n . ) . . . & f ô y . „ _ y . „ _ y . . . . . p r . . . . . . . . . . x Ï Î . . . . . . « . . . x Í . . ¿ ð . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Code:
--------------------------------2023/12/6 18:41:39--------------------------------
A memory block has been leaked. The size is: 20 This block was allocated by thread 0x32A4, and the stack trace (return addresses) at the time was: CD781E [System.pas][System][@GetMem$qqri][4949] F2AE46 [REST.JsonReflect.pas][REST.JsonReflect][Jsonreflect.TJSONConverter.OnFieldStart][1238] F37665 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3654] F38993 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3622] F38E23 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3438] F38E96 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3454] F377FB [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3689] F38993 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3622] F38E23 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3438] F3763F [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3648] F3897A [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3615] The block is currently used for an object of class: TJSONPair The allocation number is: 559108 Current memory dump of 256 bytes starting at pointer address 90B60F0: 0C 2F F0 00 01 00 00 00 50 60 0B 09 B0 5F 0B 09 00 00 00 00 FE 38 7B E1 00 00 00 00 D0 58 0B 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 EF 87 08 00 1E 78 CD 00 93 89 F3 00 23 8E F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 26 9F F3 00 33 EF F3 00 A4 32 00 00 A4 32 00 00 3A 78 CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 A8 28 F0 00 DE FA F1 15 58 42 F0 00 01 00 00 00 01 00 00 00 00 00 00 00 21 05 0E EA 84 5F 79 01 00 00 00 00 D0 58 0B 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 EC 87 08 00 1E 78 CD 00 46 AE F2 00 65 76 F3 00 93 89 F3 00 23 8E F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 . / ð . . . . . P ` . . ° _ . . . . . . þ 8 { á . . . . Ð X . . . . . . . . . . x Ï Î . . . . . ï ‡ . . . x Í . “ ‰ ó . # Ž ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó . & Ÿ ó . 3 ï ó . ¤ 2 . . ¤ 2 . . : x Í . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ¨ ( ð . Þ ú ñ . X B ð . . . . . . . . . . . . . ! . . ê „ _ y . . . . . Ð X . . . . . . . . . . x Ï Î . . . . . ì ‡ . . . x Í . F ® ò . e v ó . “ ‰ ó . # Ž ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó .
Code:
und hier noch das Summary
--------------------------------2023/12/6 18:41:39--------------------------------
A memory block has been leaked. The size is: 20 This block was allocated by thread 0x32A4, and the stack trace (return addresses) at the time was: CD781E [System.pas][System][@GetMem$qqri][4949] F38993 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3622] F38E23 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3438] F38E96 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3454] F377FB [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3689] F38993 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3622] F38E23 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalValue][3438] F3763F [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalSimpleField][3648] F3897A [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.MarshalData][3615] F39F26 [System.Generics.Collections.pas][REST.JsonReflect][Jsonreflect.%TTypeMarshaller__1$p22System.Json.TJSONValue%.Marshal][3179] F3EF33 [REST.Json.pas][REST.Json][Json.TJson.ObjectToJsonValue][202] The block is currently used for an object of class: TJSONTrue The allocation number is: 559087 Current memory dump of 256 bytes starting at pointer address 90B6190: 58 42 F0 00 01 00 00 00 01 00 00 00 00 00 00 00 21 05 0E EA 84 5F 79 01 00 00 00 00 D0 58 0B 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 EC 87 08 00 1E 78 CD 00 46 AE F2 00 65 76 F3 00 93 89 F3 00 23 8E F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 A4 32 00 00 A4 32 00 00 3A 78 CD 00 35 AE F2 00 65 76 F3 00 93 89 F3 00 23 8E F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 14 00 00 00 B0 04 02 00 29 C8 84 1E A8 28 F0 00 01 00 00 00 3C BC FA 06 00 00 00 00 00 00 00 00 D6 37 7B E1 00 00 00 00 D0 58 0B 09 00 00 00 00 00 00 00 00 78 CF CE 00 00 00 00 00 EB 87 08 00 1E 78 CD 00 46 AE F2 00 65 76 F3 00 93 89 F3 00 23 8E F3 00 96 8E F3 00 FB 77 F3 00 93 89 F3 00 23 8E F3 00 3F 76 F3 00 7A 89 F3 00 X B ð . . . . . . . . . . . . . ! . . ê „ _ y . . . . . Ð X . . . . . . . . . . x Ï Î . . . . . ì ‡ . . . x Í . F ® ò . e v ó . “ ‰ ó . # Ž ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó . ¤ 2 . . ¤ 2 . . : x Í . 5 ® ò . e v ó . “ ‰ ó . # Ž ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó . . . . . ° . . . ) È „ . ¨ ( ð . . . . . < ¼ ú . . . . . . . . . Ö 7 { á . . . . Ð X . . . . . . . . . . x Ï Î . . . . . ë ‡ . . . x Í . F ® ò . e v ó . “ ‰ ó . # Ž ó . – Ž ó . û w ó . “ ‰ ó . # Ž ó . ? v ó . z ‰ ó .
Code:
Das ist was nach einem Aufruf an Leaks passiert--------------------------------2023/12/6 18:45:08-------------------------------- This application has leaked memory. The small block leaks are: 13 - 20 bytes: TIdThreadSafeInteger x 1, TJSONArray x 2, TJSONObject x 345, TJSONTrue x 1376, TJSONFalse x 1033, TJSONPair x 4480, TJSONString x 18236, TJSONNumber x 691, UnicodeString x 688 21 - 36 bytes: TIdCriticalSection x 2, UnicodeString x 1729, Unknown x 2 37 - 52 bytes: TList<System.JSON.TJSONValue> x 2, TList<System.JSON.TJSONPair> x 345, UnicodeString x 2417 53 - 68 bytes: UnicodeString x 1600 69 - 84 bytes: UnicodeString x 2914 85 - 100 bytes: UnicodeString x 1657 101 - 116 bytes: UnicodeString x 982 117 - 132 bytes: UnicodeString x 1533, Unknown x 342 133 - 148 bytes: UnicodeString x 2230 149 - 164 bytes: UnicodeString x 871 165 - 180 bytes: UnicodeString x 1323 181 - 212 bytes: UnicodeString x 296, Unknown x 1 213 - 244 bytes: UnicodeString x 1 1509 - 1668 bytes: Unknown x 1 The sizes of leaked medium and large blocks are: 59300 |
AW: Speicherproblem mit Objekten in DLL
N'Abend
es liegt an der Delphi internen Objektserialisierung / Deserialisierung. Ich hab nun das Objekt auf die neon library umgesetellt und schon klappts. Jetzt muss ich mir nur noch überlegen ob ich das so übernehme und wie. Da hängt jetzt ein riesen Rattenschwanz dran... |
AW: Speicherproblem mit Objekten in DLL
Ich kann mir nicht Vorstellen das so ein Problem lange unentdeckt bleiben würde.
Vermutlich haben das bisher noch nicht viele mit so großen Objekten probiert oder es gibt noch immer Umstände die Du bisher noch nicht erkannt hast, warum es bei dir so durchschlägt. Egal wie, es sollte nicht auftreten und ist einen Bugreport wert. |
AW: Speicherproblem mit Objekten in DLL
Wenn du (ggf. auch nur mir per PN, das gebe ich nicht weiter) ein Beispiel schicken könntest, kann ich mir das gerne einmal anschauen. Ich benutze die Klassen selbst und habe nicht solche Leaks.
|
AW: Speicherproblem mit Objekten in DLL
Zitat:
|
AW: Speicherproblem mit Objekten in DLL
@BastiFantasti , Hi
For me this behavior looks like dangling pointers (by-copy), this of course will leads to memory leak but not exactly as traditional just not-freed. So my thoughts here: 1) you can increase the stack reported by FastMM for the leaks by adjusting a constant in FastMM4.pas to something like 30, it might help, or you can use EurekaLog as it will report the leaks with far more accuracy, as i can't see if the record (you mentioned in the second post) in the report, did it leak too ? 2) the most crucial thing is to check and then double check, how these record and objects being passed to the DLL, i mean how did you declare the parameters for these managed types or that record, are these "const" or "var" or left as default without modifier, each one will behave differently and this might cause this copy, hence increasing the ref count causing this leak. 3) are doing any sort of casting on managed type or that record? is it passed by pointer or as const ? you can also track its refCount (or any of its managed type field) in memory before calling from the EXE and compare on the DLL after that call. Hope that helps. |
AW: Speicherproblem mit Objekten in DLL
Zitat:
|
AW: Speicherproblem mit Objekten in DLL
Das Problem ist behoben.
Es war ein nicht freigegebenes JSON Objekt bei der Objektserialisierung. Für die anderen, die auch in diese Verlegenheit kommen:
Code:
Hier hatte ich vergessen das TJsonObject freizugeben :oops:
var
jo: System.Json.TJsonObject; begin try jo := rest.Json.TJson.ObjectToJsonObject(aObject); Result := jo.Format(DEF_JSON_INDENT); finally freeandnil(jo); end; end; d.h. der Fehler war nicht bei Delphi zu suchen, sondern 40cm vor dem Bildschirm. |
AW: Speicherproblem mit Objekten in DLL
Hallo,
hätte FastMM4 nicht wenigstens das Objekt anzeigen müssen? |
AW: Speicherproblem mit Objekten in DLL
Zitat:
Klar, wenn man es dann erst weiß, ist es total logisch, auch dem Threadersteller. Aber wie es halt so ist... wenn man sucht und sucht, in die falsche Richtung schaut, ... Wem ist es noch nicht so ergangen? Mir auf jeden Fall schon oft. Wichtig ist, dass man daraus lernt, so dass man beim nächsten Mal weniger lange sucht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz