![]() |
Stringlisten in mehreren Prozeduren nutzen
Hallo,
wenn ich wie folgt Stringlisten nutze, bekomme ich eine Zugriffsverletzung:
Delphi-Quellcode:
Muss die Stringlist nach jedem Schreiben geschlossen werden? Wenn ja, wie hänge ich an?var sl:TStringlist; Procedure A; Begin SL := TStringList.Create; SL('Text ; Text'); b; c; end; Procedure b; Begin SL.Add('Text ; Text'); //<-Exception end; Procedure c; Begin SL.SaveToFile('datei.csv'); end; MFG Steffen |
Re: Stringlisten in mehreren Prozeduren nutzen
Hallo,
die Stringliste ist nur dort gültig, wo Du sie erzeugst. Du solltest sie also global erzeugen. Edit: Schwachsinn - ich meine natürlich, dass sie nur dort gültig ist, wo Du sie deklarierst. Edit2: Zitat:
Allgemein: Wenn Du eine Stringliste in allen Methoden einer Klasse benutzen möchtest, dann solltest Du sie auch in der Klasse deklarieren. Am Beispiel einer Klasse TForm1 sieht das dann ungefähr so aus:
Delphi-Quellcode:
Du könntest dann auf 'sl' in allen Methoden Deiner Klasse 'TForm1' zugreifen.
Unit Unit1;
Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; Type TForm1 = Class(TForm) Procedure FormCreate(Sender: TObject); Procedure FormDestroy(Sender: TObject); private sl: TStringlist; End; Var Form1: TForm1; Implementation {$R *.dfm} Procedure TForm1.FormCreate(Sender: TObject); Begin sl := TStringlist.Create; End; Procedure TForm1.FormDestroy(Sender: TObject); Begin FreeAndNil(sl); End; End. Willst Du auch in klassenfremden Methoden auf sl zugreifen, so musst Du die Sichtbarkeit erhöhen, oder eine Property mit entsprechenden read/write-Methoden zur Verfügung stellen, oder die Stringliste global deklarieren. Edit3: Rechtschreibfehler in Edit2 behoben :mrgreen: |
Re: Stringlisten in mehreren Prozeduren nutzen
Ich kann das Problem nicht nachvollziehen :gruebel:
Hier mal eine Testunit:
Delphi-Quellcode:
unit UnitNix;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private-Deklarationen } sl: TStringList; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin sl := TStringList.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(sl) then FreeAndNil(sl); end; procedure TForm1.Button1Click(Sender: TObject); begin if Assigned(sl) then begin sl.Add('eine Zeile'); Button2Click(self); Button3Click(self); end; end; procedure TForm1.Button2Click(Sender: TObject); begin if Assigned(sl) then sl.Add('eine weitere Zeile'); end; procedure TForm1.Button3Click(Sender: TObject); begin if Assigned(sl) then sl.SaveToFile('C:\blablubb.txt'); end; end. |
Re: Stringlisten in mehreren Prozeduren nutzen
Das sollte so aber funktionieren...
|
Re: Stringlisten in mehreren Prozeduren nutzen
Vielleicht hat er seine Variable in einer Klasse deklariert. Lt. seines Quelltextes sieht es zwar nach einer globalen Deklaration aus, aber vielleicht ist das einfach nur ein Copy&Paste-Fehler...
|
Re: Stringlisten in mehreren Prozeduren nutzen
Somit fischen wir mal wieder im Trüben.
|
Re: Stringlisten in mehreren Prozeduren nutzen
Vielleicht kommt der Fehler auch daher:
Delphi-Quellcode:
Das self bezieht sich nämlich auf das Form und nicht auf den Button1.
Button2Click(self);
Button3Click(self); Besser wäre vermutlich:
Delphi-Quellcode:
Button2Click(Sender);
Button3Click(Sender); |
Re: Stringlisten in mehreren Prozeduren nutzen
Moment, bei mir kommt kein Fehler, nicht verwechseln ;)
|
Re: Stringlisten in mehreren Prozeduren nutzen
Zitat:
Edit: Delphi-Tag geöffnet |
Re: Stringlisten in mehreren Prozeduren nutzen
Er fragt ab, ob die Variable ein Objekt referenziert
|
Re: Stringlisten in mehreren Prozeduren nutzen
Zitat:
|
Re: Stringlisten in mehreren Prozeduren nutzen
Es prüft nur auf Nil. wenn das Objekt bereits zerstört ist, liefert .Assigned natürlich true. deshalb ist es ja sinnvoll FreeAndNil zu verwenden
|
Re: Stringlisten in mehreren Prozeduren nutzen
Ja, das ist mir schon klar.
Aber Du stimmst mir doch sicherlich zu, dass das Assigned an dieser Stelle überflüssig ist, da ein einfaches FreeAndNil(sl) ausreichen würde, oder? Bin gerade etwas verwirrt. |
Re: Stringlisten in mehreren Prozeduren nutzen
Kommt wieder zurück zum eigentlichen Thema...
|
Re: Stringlisten in mehreren Prozeduren nutzen
Doppelt hält halt besser :)
|
Re: Stringlisten in mehreren Prozeduren nutzen
Zitat:
Aber ich glaube, dass wir nicht weiterkommen, solange WIng2005 nicht mal die Senftube öffnet. |
Re: Stringlisten in mehreren Prozeduren nutzen
So nun ich mal wieder....
Ich kann leider erst am Montag testen, was ihr so schreibt (Delphi habe ich leider nur an der Arbeit und ab heute ist Wochenende :-D ). Die Stringlist ist einfach im public-Teil der Unit deklariert. In der Prozedur, in welcher die Liste als solche erzeugt wird, kann ich uneingeschränkt schreiben (A). Jedoch bricht die Anwendung ab, sobald ich in B versuche selbiges zu tun. Das ist mein ganzes Problem.... MFG Steffen |
Re: Stringlisten in mehreren Prozeduren nutzen
Zitat:
Zitat:
Delphi-Quellcode:
Wir sind nun leider nicht schlauer, als wir es vor Deiner Antwort waren :wink:
Unit Unit1;
Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; Type TForm1 = Class(TForm) private { Private-Deklarationen } //<--hier private (in der Klasse TForm1) public { Public-Deklarationen } //<--hier public (in der Klasse TForm1) End; Var Form1: TForm1; sl: TStringlist; //<-- hier global Implementation {$R *.dfm} End. |
Re: Stringlisten in mehreren Prozeduren nutzen
Nur mal nebenbei: Globale Objekte sollte man über ein Singleton absichern, sprich: eine Funktion zum Zugriff deklarieren. Im Initialzation-Abschnitt wird der Zeiger auf Nil gesetzt, im finalization das Objekt zerstört und in der Funktion erstelle, falls es noch nicht erstellt wurde, also z.B. so:
Delphi-Quellcode:
Dann ist auch gewährleistet, dass diese Liste auch erstellt wird bei Benutzung. So wird allerdings die vorzeitige Zerstörung nicht verhindert, da muss man dann noch aufpassen. Solange man nur über die Funktion zugreift und den Destruktor nicht ruft, passiert nix.
Unit Foo;
Interface Function MyStringList: TStringList; Implementation Var oMyList: TStringList; Function MyStringList: TStringList; Begin If Not Saaigned(oMyList) Then oMyList:=TStringList.Create; Result:=oMyList; End; ... Initialization oMyList:=Nil; Finalization FreeAndNil(oMyList); End. |
Re: Stringlisten in mehreren Prozeduren nutzen
Zitat:
|
Re: Stringlisten in mehreren Prozeduren nutzen
Darauf hinweisen, dass einne globale Instanz gesichert werden muss, damit man sie nicht verwendet, bevor sie angelegt (.create) wurde, denn das führt zu Zugriffsverletzungen. Ausserdem sollte sowas geregelt zurückgeabut werden (Ja nach Beenden der Applikation wird der Speicher eh wieder frei, aber bei sowas kanns auf die Reihenfolge ankommen).
|
Re: Stringlisten in mehreren Prozeduren nutzen
Ja,
das ist allgemein bekannt, dass man kein Spanferkel essen kann, bevor es geboren wurde. Nur mit Deinem Code-Beispiel und den dazu gehörigen Erläuterungen komme ich ehrlich gesagt nicht ganz klar. *Ratter-ratter* Ah, ok - jetzt verstehe ich. Du greifst auf Deine Stringliste nicht direkt zu, sondern über eine Funktion, die dafür sorgt, dass die Stringliste erzeugt wird, sofern noch nicht geschehen. Da ich in der Regel keine globalen Objekte nutze, war mir der Grund für Dein Konstrukt nicht auf Anhieb klar; sorry. Edit: Rechtschreibfehler eingebaut. |
Re: Stringlisten in mehreren Prozeduren nutzen
Das mit der Stringliste ist ja nur ein Trivialbeispiel.
Manchmal benötigt man solche Konstrukte, für z.B.: eine Factory, die einem Instanzen von registrierten Klassen liefert. Ist dann praktisch, wenn solche Klassen für Kundenanpassungen überschrieben werden müssen. Dann reicht es der Factory zu sagen, wenn Klasse X angefordert wird, gib eine Instanz von abgeleiteter Klasse Y zurück. Erspart viel Schreibarbeit und man kann sichergehen, dass überall die Klasse ersetzt wird. Im Projekt meiner Firma werden z.B.: die Dialoge über eine Art Scriptsyntax erstellt. Da steht halt im Script einfach der Klassenname drin. |
Re: Stringlisten in mehreren Prozeduren nutzen
Sorry, dass ich derzeit ein winig passiv war (war ein anstrengendes WE)....
@s-off:bisher habe ich es genau so gemacht, wie du im 2. Beispiel gezeigt hast. (...also ausserhalb jeglicher Klassendeklaration deklariert....). Die weiteren aufgeführten Anmerkungen, die hier angesprochen wurden, sind für mich nicht wirklich nachvollziehbar (vielleicht hätter der Titel mit "Noob braucht Hilfe..." beginnen sollen.) Der eigentliche Grund für die Stringlisten ist, dass ich über mehrere Proceduren hinweg Informationen sammeln (Format: "Text ; Text; Text") kann, welche dann einfach in eine CSV geschrieben werden. Diese dienen dann als "Protokoll" einer Berechnung. Da die Infos aber in mehreren Prozeduren und Funktionen entstehen, muß ich global auf die gleiche Stringliste zugreifen können... Das ist schon alles. Schöner wäre natürlich (habe ich so aber noch nicht gesehen), wenn ich die CSV direkt beschreiben könnte. Bisher habe ich eine korrekte Spaltentrennung nur via Stringlisten hinbekommen. MFG und danke für die zahlreichen Hinweise Steffen |
Re: Stringlisten in mehreren Prozeduren nutzen
Das Problem hat sich geklärt. Bin alles nochmal durchgegangen und habe festgestellt, dass das erste
Schreiben in die Liste VOR dem eigentlichen Erzeugen stattfand. Dumm! Naja, habe es entsprechend geändert... MFG Steffen |
Re: Stringlisten in mehreren Prozeduren nutzen
sag mal, warum machste es nicht so, wie in der prozeduralen progammierung...
Delphi-Quellcode:
procedure main;
var sl: tstringlist; begin sl := tstringlist.create; try sub(sl); finally sl.free; end; end; procedure sub(const sl: tstrinlist); begin // mach irgendwas mit sl... end; |
Re: Stringlisten in mehreren Prozeduren nutzen
Im Endeffekt mache ich es ja so, nur dass ich die SL nicht jedesmal übergebe, sondern (auch aus Gründen der vielen
Änderungen, die ich sonst vornehmen müßte) deklariere sie global. MFG Steffen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:22 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