Autor Beitrag
mczero098
Hält's aus hier
Beiträge: 9

Win XP, Win 7
Delphi 7 Enterprise, JAVA, PHP, JScript, SQL...
BeitragVerfasst: Mo 16.01.12 15:09 
Halli Hallo,

anbei, ich bin nicht ganz neu hier im Forum, bzw. war zuvor immer nur lesend tätig.. Aber nun wirds mal Zeit das
ich auch selber das Forum nutze.. ich komme nämlich nicht weiter!!

Ich habe hier eine Methode, die eine StringList zurückgibt. Der Methode wird ein String übergeben, dieser wird dann quasi ähnlich der PHP-Funktion explode() als StringList zurückgegeben, das ist im Prinzip alles, was die Methode macht. Sie soll aus Strings wie "23/24" oder "20-3/26" praktisch die einzelnen, maximal zweistelligen Zahlen extrahieren.

So weit, so schön! Alles funktioniert. Jedoch beim ca. 136ten durchlauf hängt die Anwendung in der ersten Zeile TStringList.Create und der Speicherverbrauch steigt, bis eine EOutOfMemory Exception kommt.

Ich habe FastMM ausprobiert, jedoch wird das LogFile selber, nachdem die Exception auftritt, Gigabyteweise groß.. Bekomme sie so nicht geöffnet..


Kann mir einer erklären, was da vor sich geht?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
function TpdoxImport.splitRSatz(kombinationsSatz: String): TStringList;
var
  i : integer;
  resultStringList : TStringList;
  singleRSatz : String;
begin
  resultStringList := TStringList.Create;
  i := 1;
  while i <= length(kombinationsSatz) do
  begin
    singleRSatz := '';
    if regExprZahlen.Exec(kombinationsSatz[i]) then
    begin
      singleRSatz := singleRSatz + kombinationsSatz[i];
      if i < length(kombinationsSatz) then
        if regExprZahlen.Exec(kombinationsSatz[i+1]) then
        begin
          singleRSatz := singleRSatz + kombinationsSatz[i+1];
          i := i + 2;
        end
        else
        begin
          i := i + 1;
        end;
      resultStringList.Add(singleRSatz);
    end
    else
    begin
      i := i + 1;
    end;
  end;
  result := resultStringList;
end;


Ach ja, ich arbeite mit Delphi 7 Enterprise.

Vielen Dank im Voraus für die Mühen!! Ich bin gerade ratlos/oder stehe einfach nur auf dem Schlauch.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 16.01.12 15:24 
Wo wird die Stringliste denn wieder freigegeben? Grundsätzlich gibt es eigentlich nur drei sinnvolle Möglichkeiten:
  • Erstellen im Konstruktor, Freigabe im Destruktor
  • Erstellen vor einem Methodenaufruf, freigeben danach
  • Direkt erstellen und in der selben Methode wieder freigeben
Dabei gibt man die Ressource immer an der selben Stelle / Ebene wieder frei, an der man sie reserviert hat. Deine Methode (ein erstelltes Objekt zurückliefern :shock:) ist dagegen äußerst unsauber...

Beispiel:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TpdoxImport.splitRSatz(kombinationsSatz: String; AValues: TStringList);

...
var
  MyList: TStringList;
begin
  MyList := TStringList.Create;
  try
    splitRSatz('', MyList);
    ...
  finally
    MyList.Free;
  end;
end;
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mo 16.01.12 15:28 
Genau das wollte ich auch schreiben, aber Sebastian kam mir zuvor. Was mit create erzeugt wurde, muss letztlich auch u.a. mit free wieder freigegeben werden, wie Sebastian schrieb. Außerdem denke ich nicht, dass Du diese Split-Ergebnisse alle speicherst, sondern nur jeweils bei der Prozedur benötigst, später dann gefahrlos löschen kannst (siehe Sebastians Konstrukt).

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
mczero098 Threadstarter
Hält's aus hier
Beiträge: 9

Win XP, Win 7
Delphi 7 Enterprise, JAVA, PHP, JScript, SQL...
BeitragVerfasst: Mo 16.01.12 15:36 
Ja das stimmt, das Objekt wird außerhalb der Methode wieder freigegeben. Ich dachte aber immer, das wäre OK,
ich bin ja noch nicht ewig Delphi Entwickler und zuvor wurde mir die Praxis in JAVA genau so desöfteren beigebracht *schäm*

Denn gedanklich ging ich immer davon aus, das hier immer nur mit einem Objekt gehandelt wird, jedoch mit wechselnden Referenzen darauf..

Ich probiere mal die Erstellung außerhalb der Methode.. Danke schon einmal..
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mo 16.01.12 15:50 
Das Entscheidende ist immer, dass es auf der gleichen Ebene freigegeben wird, auf der es erzeugt wird. Denn Du weißt ja nicht, in wieweit z.B. die Prozedur nicht doch merhfach aufgerufen wird, bevor die Freigabe erfolgt. Und dann ist nur eine Komponente freigegeben, die andere/n nicht. Schau dir Sebastians Kosntrukt an. Dort ist es auf der selben Ebene und nur ein Aufruf pro Erzeugung und Freigabe möglich. Selbst wenn ein Fehler auftritt, wird die Freigabe abgearbeitet. Ansonsten würde die Prozedur (ohne den Try .. finally .. end Konstrukt) möglicherweise ohne Freigabe abgearbeitet.

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 16.01.12 15:55 
user profile iconmczero098 hat folgendes geschrieben Zum zitierten Posting springen:
ich bin ja noch nicht ewig Delphi Entwickler und zuvor wurde mir die Praxis in JAVA genau so desöfteren beigebracht *schäm*
Dort ist das auch in Ordnung, denn Java hat (wie .NET) einen Garbage Collector und gibt die Objekte selber wieder frei. ;-)
zuma
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 660
Erhaltene Danke: 21

Win XP, Win7, Win 8
D7 Enterprise, Delphi XE, Interbase (5 - XE)
BeitragVerfasst: Mo 16.01.12 16:21 
Stringlisten sind toll, wenn man sie geschickt benutzt und können einem ne Menge Arbeit abnehmen ;)

ich erlaub mir mal so eine kleine 'Klugscheißerei',
was mit Stringlisten alles so geht (anhand der von dir gegebenen Daten):

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
procedure StringZerlegen(xString : String; xTrenner : char; xListe : TStringList);
var lSl : TStringList;
begin
 lSl := TStringList.Create;
 try
  lSl.Delimiter       := xTrenner;
  lSl.StrictDelimiter := True;
  lSl.DelimitedText   := xString;
  xListe.Text         := lSl.Text;
 finally
  lSl.Free;
 end;
end;

// Testaufruf
procedure THauptmenu.Button2Click(Sender: TObject);
var lSl : TStringList;
    x : integer;
begin
 inherited;
 lSl := TStringList.Create;
 try
  StringZerlegen('23/24;20-3/26'';', lSl);
  ShowMessage(lSl.Text);
  StringZerlegen(lSl.Text, '/', lSl);
  ShowMessage(lSl.Text);  
  StringZerlegen(lSl.Text, '-', lsl);
  ShowMessage(lSl.Text);
 finally
  lSl.Free;
 end;
end;

_________________
Ich habe nichts gegen Fremde. Aber diese Fremden sind nicht von hier! (Methusalix)
Warum sich Sorgen ums Leben machen? Keiner überlebts!
mczero098 Threadstarter
Hält's aus hier
Beiträge: 9

Win XP, Win 7
Delphi 7 Enterprise, JAVA, PHP, JScript, SQL...
BeitragVerfasst: Mo 16.01.12 16:31 
Es läuft nun! Allerdings war das Problem die While-Schleife in der Methode..
Wenn der Eingabestring nur einstellig ist (und das war er beim x-ten Durchlauf...), dann ist das natürlich eine
Endlosschleife.. ich war blind :D Und heute vollkommen übermüdet.. Warum er vorhin allerding bei xxx := TStringList.Create hing weiß ich nicht..
muss wohl wie gesagt mit der unsauberen Erzeugung/Zerstörung zusammenhängen.

@Tranx Abgesehen vom eigentlich Problem habe ich nun wie schon vorgeschlagen Erzeugung und Zerstörung an einem Ort erledigt :)

@jaenicke jup da hast Du recht.. da ist ein wenig Umdenken meinerseits erforderlich! Das Prinzip habe ich eigentlich verstanden, nur war ich ein wenig sorglos an welchen Stellen ich was erzeuge und wieder freigebe..

@zuma Sieht nett aus! Das man da mit Delimitern arbeiten kann war mir gar nicht bewusst :D


Generell verspüre ich oft den Wunsch, einfach öfter zu Wissen was als Sauber und was als Unsauber gilt. Auch wenn mein obiges Negativbeispiel ja eigentlich einleuchten sollte!
Gibts irgendwo Tutorials ála "Delphi Clean Code" ?