![]() |
Dynamische Arrays in Records
Ok, ich bin grade etwas verwirrt, weil ich nicht genua weiß wie Delphi damit umgehen würde, aber ihr wisst das sicher. :P
Gegeben ist folgender Record-Type:
Delphi-Quellcode:
Das ganze Ding soll vie Netzwerk rausgeschickt werden und logischerweise auch wieder eingelesen.
TChatMsg = record
Code: Byte; //Statuscode Lenght: Cardinal; //Contentlänge Content: array of Byte; end; Dazu muss auf der Gegenseite natürlich auch so ein Ding erstellt werden, auch kein Problem, die Frage ist, wenn ich das Array gefüllt habe und den Record-Type frei gebe (dispose), was passiert dann? Weiß Delphi, das das Array mit freigegeben werden muss, oder muss ich seine Länge zunächst auf 0 reduzieren (oder mit anderen Worten repräsentiert das Array für Delphi nur nen Pointer). Oder wäre es vielleicht sinvoller die Sache anders anzugehen und das ganze eher so zu definieren (und entsprechen Speicher manuell zu reservieren):
Delphi-Quellcode:
Wahrscheinlich ne dumme Frage, aber ich dachte, bevor ichs schreib ist villeicht günstiger, erst drüber nachzudenken, wie ich die Speicherverwaltung hinterher am günstigsten bewältige. :zwinker:
TChatMsg = record
Code: Byte; //Statuscode Lenght: Cardinal; //Contentlänge Content: Pointer; end; |
Re: Dynamische Arrays in Records
Delphi weiß, dass da ein dynamisches Array (oder ein String) drin ist und gibt ihn frei. Da ist ein wenig Compiler-Magic im Spiel. Er unterscheidet zwischen "dynamischen" Records (also Records mit min. eine dynamischen Variable) und statischen Records.
Es gibt dazu zwei verschiedene dispose-Funktionen. Die dynamische Variante rentt dann rekursiv durch dein Record durch (mit Hilfe der RTTI). Aber wie versendest du einen Record mit dynamischen Inhalt übers Netz? |
Re: Dynamische Arrays in Records
Binär, hatte ich mir das gedacht, am absender kenne ich ja die Größe und der Empfänger kann die Lenght ja auslesen und dann entsprechend viel mehr lesen. Das müsste ich bei der Pointervariante allerdings auch machen.
Bleibt nun die Frage was günstiger ist, kannst du das nochmal genauer erklären? Also würde ein dispose(MyChatMsg); bei gefüllten Inhalt (sei es nun ein String ode binäre Daten, ist beides vorgesehen) funtionieren, ohne ein Memory-Leak zu hinterlassen? Wie sieht das mit der Performance aus, rekursiv bedeutet da ja meistens nichts so gutes, mit dem Pointer müsste ich aber auch manuell im Prinzip nichts anderes als erst:
Delphi-Quellcode:
[Edit] Die Sache hat sich denke ich erledigt, weil mir grade der Vorteil erst auffällt, dass ich wenn ich das Array nehm, ich ja den ganzen Record im Speicher behalten muss, weil ich ihn nicht freigeben kann, ohne das Array dabei zu verlieren (wenn ich alles richtig versteh) oder es erst zu kopieren, aber das ist nicht der Sinn der Sache. Wenn ich den Pointer nehm, kann ich den Inhalt unabhängig vom Rest der Nachricht behalten. Die prinzipielle Fragestellung, was besser funktioniert, würde mich aber trotzdem noch intressieren.
dispose MyChatMsg.Content //Content: Pointer
dispose MyChatMsg; |
Re: Dynamische Arrays in Records
Genauer erklären?
Die RTTI eines Records kann so beschrieben werden:
Delphi-Quellcode:
//RTTI eines Records
type PPropContent=^TPropContent; TPropContent=record //je ein dynamisches Element des Records RecordData:ppointer; //RTTI einer dynamischen Variablen innerhalb des Records Position:cardinal; //Position der Variablen im Record end; type PRecordData=^TRecordData; //Zeiger auf RTTI TRecordData=record size:cardinal; //Größe des Records insgesamt PropCount:cardinal; //Anzahl der dynamischen Komponenten Content:array[0..16737] of TPropContent; //max(content) liegt natürlich bei PropCount end; Im statischen Fall würde bei einem statischen Record dein dispose vom Compiler durch freemem ersetzt (die Größe kennt der Compiler ja) In deinem speziellen Fall wird dispose aufgerufen und noch als zweiter Parameter ein Zeiger auf die RTTI deines Records übergeben (typeInfo(TmyRecord): PRecordData). In dieser RTTI steht die Größe deines Records drinn (für Freemem) und noch die Anzahl dynamischer Elemente (bei dir ein Array) Und dann kommt eine List (TPropContent) mit der Postion der Variable im Array und einen Zeiger auf die RTTI dieser Variablen. Und genau dort schaut er jetzt und sieht, dass es ein Array ist und ruft dann finalizeArray auf. Über Zeitprobleme würde ich dabei nicht reden und die bequeme Variante über das Array wählen. (Ansonsten könntest du ja gleich in C programmieren :mrgreen: ) |
Re: Dynamische Arrays in Records
Vielen Dank für deine Mühe :thumb: , das ist intressantes Hintergrundwissen dazu (ich hasse es immer, wenn die Compiler-magic was macht und ich kann nicht sagen was). Ich entscheide mich aus obigen Grund trotzdem mal für den Pointer, nicht daas die paar Bytes die ich behalten müsste groß was ausmachen, aber ich kann noch nicht abschätzen, ob ich dasirgendwann mal für was benutze, wo ich die Daten länger brauch und will die Unit nicht jedesmal umschreiben müssen. :wink:
Zitat:
[Edit]Code-Tag erwischt gehabt :wall: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:28 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