![]() |
Speicher Freigeben
Hallo,
ich habe folgende Funktion:
Delphi-Quellcode:
Aufgerufen wird diese zB so:
function ExtraColumsStringsDB(firma:string):TStringlist;
var Temp: Array Of TColumn; i: integer; begin Result := TStringList.Create; Temp := GetExtraFields(firma); for i:=0 to high(Temp) do begin result.Add(Temp[i].FieldName ); end; end;
Delphi-Quellcode:
Allerdings ist mir aufgefallen, dass bei dieser Vorgehensweise der verwendete Speicher der Funktion niemals freigegeben werden kann. (FPC hat ja keinen Garbage Collector)
ExtraColumsStringsDB('name').count
Wenn man den Speicher in der Funktion freigeben würde, könnte man den Rückgabewert (TStringlist) ja niemals benutzen. Gibt es irgendeine Möglichkeit diese nicht mehr verwendeten Variablen nach Ausführung der Funktion wieder freizugeben ? Grüße stiftII |
AW: Speicher Freigeben
So was löst man in der Regel, in dem der Aufrufer das Objekt zur Verfügung stellt und es der Routine übergibt.
|
AW: Speicher Freigeben
Mach es doch so, dass eine StringList der Methode übergeben werden muss.
Dann noch überprüfen ob die überhaupt existiert, sie vll. clearen und mit Werten füllen. MfG Alaitoc Edith sagt: "Luckie war schneller". |
AW: Speicher Freigeben
oder den Funktionsnamen so wählen das klar ist das der Aufrufer aufräumen muss. z.B. CreateExtraColumsStrings
|
AW: Speicher Freigeben
Hi,
ich würde das Ganze ein wenig anders angehen (auch wenn schon Antworten da sind, hier die mögliche Lösung):
Delphi-Quellcode:
function ExtraColumsStringsDB(firma:string; const ASL: TStringlist): Boolean;
var Temp: Array Of TColumn; i: integer; begin try Result := True; Temp := GetExtraFields(firma); for i:=0 to high(Temp) do begin ASL.Add(Temp[i].FieldName ); end; except Result := False; end; end; procedure dosomething; var SL:TStringList; begin SL := TStringList.Create; try ExtraColumsStringsDB('EINEFIRMA', SL); finally SL.Free; end; end; |
AW: Speicher Freigeben
Die Liste als Parameter zu übergeben ist trotzdem die bessere Option, da sonst bei mehrfachem Aufruf der Funktion auch mehrere Instanzen erzeugt werden. Wenn man dann nicht jede in einer Variablen speichert und freigibt hat man die schönsten Speicherlecks produziert.
|
AW: Speicher Freigeben
Zitat:
Gruß K-H |
AW: Speicher Freigeben
Zitat:
|
AW: Speicher Freigeben
Zitat:
![]() |
AW: Speicher Freigeben
Und wenn man den Parameter noch als TStrings (statt TStringList) deklariert, kann man sogar so Spielchen machen wie Memo.Lines übergeben...
mfg Christian |
AW: Speicher Freigeben
Vielen Dank :) .. werde es dann so machen, dass ich eine temp Variable mit übergebe und aus der Funktion mache ich dann eine Prozedur.
Dachte es gäbe vllt, wie bei Java eine Möglichkeit nicht benötigte Resourcen zu identifizieren und freizugeben. stiftII |
AW: Speicher Freigeben
Zitat:
|
AW: Speicher Freigeben
Zitat:
|
AW: Speicher Freigeben
Kurze Frage nochmal hierzu.
Warum funktioniert das so nicht ("function ExtraColumsStringsDB" erstellt die Stringlist) ?
Delphi-Quellcode:
function ExtraColumsStringsDB(firma:string; ASL: TStringlist): Boolean;
var Temp: Array Of TColumn; i: integer; begin try Result := True; SL := TStringList.Create; Temp := GetExtraFields(firma); for i:=0 to high(Temp) do begin ASL.Add(Temp[i].FieldName ); end; except Result := False; end; end; procedure dosomething; var SL:TStringList; begin try ExtraColumsStringsDB('EINEFIRMA', SL); finally SL.Free; end; end; |
AW: Speicher Freigeben
Weil der Stringlisten-Parameter const deklariert ist? Aber das ist die merkwürdigste Variante, die ich hier bislang gesehen habe, ist das nur zum Herumprobieren, oder willst Du das tatsächlich produktiv so einsetzen?
|
AW: Speicher Freigeben
Zitat:
Ja, ich würde das gerne "produktiv einsetzen" ;). Meine Funktion/Prozedur sieht so aus:
Delphi-Quellcode:
Das geht so auch, mich würde nur interessieren, warum die andere Variante nicht funktioniert (Access Violation).
procedure ExtraColumnsStringsDB(firma:string; ColumnStrings:TStringlist);
var Temp: Array Of TColumn; i: integer; begin Temp := GetExtraFields(firma); for i:=0 to high(Temp) do begin ColumnStrings.Add(Temp[i].FieldName ); end; //Free all columns for i:=0 to high(Temp) do begin Temp[i].Free; end; end; Grüße stiftII |
AW: Speicher Freigeben
Rein akademisch: ich denke, wenn Du es so machen willst, musst Du SL als Var-Parameter übergeben.
|
AW: Speicher Freigeben
Zitat:
K-H |
AW: Speicher Freigeben
Da fehlt nen A in der Funktion. Hatte die nur so kopiert :x
Jetzt aber:
Delphi-Quellcode:
function ExtraColumsStringsDB(firma:string; ASL: TStringlist): Boolean;
var Temp: Array Of TColumn; i: integer; begin try Result := True; ASL := TStringList.Create; Temp := GetExtraFields(firma); for i:=0 to high(Temp) do begin ASL.Add(Temp[i].FieldName ); end; except Result := False; end; end; procedure dosomething; var SL:TStringList; begin try ExtraColumsStringsDB('EINEFIRMA', SL); finally SL.Free; end; end; |
AW: Speicher Freigeben
Zitat:
sollte er es sogar mit OUT, anstatt VAR deklarieren, damit man gleich weiß was auf einen zukommt, wenn man diesen Funktionsheader sieht. |
AW: Speicher Freigeben
Das stimmt zwar, aber ich halte die gezeigte Vorgehensweise sowieso zumindest für problematisch. Schaut man sich dosomething alleine an, dann ist man doch erst einmal verwirrt.
|
AW: Speicher Freigeben
Das würde ich unter tricky noch akzeptieren, ich käme hier ins Grübeln:
Delphi-Quellcode:
das mag zwar gehen, aber wenn man mal die Übersicht verliert...
function ExtraColumsStringsDB(firma:string; ASL: TStringlist): Boolean;
...... ASL := TStringList.Create; Gruß K-H |
AW: Speicher Freigeben
Naja, eine lokale Instanzvariable, die nirgends erzeugt, aber dann freigegeben wird... Da würde ich zunächst mit einer AV rechnen.
|
AW: Speicher Freigeben
na ja, übersichtlich ist anders. Wenn man konsequent den Spiecher auch da wieder frei gibt, wo er reserviert wird, dann läuft man auch nicht in Gefahr den Überblick zu verlieren.
|
AW: Speicher Freigeben
Japp. Aus dem Bauch heraus würde ich es ungefähr so machen:
Delphi-Quellcode:
function ExtraColumsStringsDB(const firma: string; ASL: TStrings): Boolean;
var Temp: Array Of TColumn; i: integer; begin Result := False; Assert(Assigned(ASL)); try ASL.Clear; //das sieht mir komisch aus, ist das auch so ein Kandidat? Temp := GetExtraFields(firma); for i:=0 to high(Temp) do begin ASL.Add(Temp[i].FieldName ); end; Result := True; except on E: Execption do //irgendwie reagieren end; end; procedure dosomething; var SL: TStringList; begin SL := TStringlist.Create; try ExtraColumsStringsDB('EINEFIRMA', SL); //noch irgendetwas mit SL anstellen finally SL.Free; end; end; |
AW: Speicher Freigeben
Gibt es irgend einen Grund für das try..except in ExtraColumsStringsDB? Wenn mand ie Exception nicht behandeln kann, dann sollte die auch nicht behandelt werden und erst in einer höheren Schicht taucht dann das try..except auf. Dann kann man sich auch den überflüssigen Boolean-Rückgabewert sparen.
mfg Christian |
AW: Speicher Freigeben
Zitat:
Interfaces, dynamische Arrays und Strings kann man daher ganz gut als Result verwenden. Einfache Typen, Records, statische Arrays und natürlich eine Kombination aus all Diesen sind natürlich auch möglich. |
AW: Speicher Freigeben
Da die Elemente aber anscheinend eine Eigenschaft Fieldname haben, wird es sich wohl um Records oder Objekte handeln. Und Objekte werden in dem Code ja nicht freigegeben, daher meine Frage.
|
AW: Speicher Freigeben
Von Objekten hab ich auch nichts gesagt :mrgreen:
Records in Arrays wären aber OK :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:09 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