![]() |
Delphi-Version: 5
TStringList - Zugriff auf property
Hallo Leute,
in Delphi XE3 ist ein Bug, der zuweilen beim Zugriff von Listen auftritt. Ich habe nie herausgefunden, wann genau. Wir werden es auch nicht lösen, sondern ich bitte Euch, mir beim Basteln eines Workarounds zu helfen. Ich will zugreifen auf ein Feld(?) eines StringLists, also z.B. mit s:=StringList1[0]; Dabei knallt es so, dass ich die IDE neu starten muss, was an Delphi liegt. Intern wird dieser Wert gespeichert in einem array(?) StringList1.FList[0], wenn ich nicht irre. Das StringList1 sieht im Debug Fenster sauber aus. Sein internes property(?) StringList1.FList[0] hat genau den Wert, den ich gerne zugreifen würde. Delphi sollte darauf mit StringList1[0] zugreifen, das eben funktioniert in der XE3 Version in einigen Fällen nicht! StringList1[0] zeigt mir dann auch im Debugger "inaccessible value". So der langen Rede kurzer Sinn: Hat jemand eine Idee, wie ich StringList1.FList[0] zugreifen kann? Der Wert ist derselbe, jedoch ist das property private und kann im Code nicht verwendet werden. Danke für Tipps! |
AW: TStringList - Zugriff auf property
Zitat:
|
AW: TStringList - Zugriff auf property
Hallo,
Zitat:
|
AW: TStringList - Zugriff auf property
Ich gehe auch mal davon aus, dass es nicht an Delphi liegt, sondern an einem Fehler im Code.
Du könntest zum einen verschiedene Prüfungen vornehmen, ob die Liste gültig ist bzw. der Indexeintrag. Wenn der nicht gültig ist, sollte eigentlich nur ein Listindex-Fehler auftreten. Test etwa so:
Delphi-Quellcode:
Du könntest bei Deiner speziellen Problemstellung im Debugger auch Prüfen, wie der Inhalt von StringList1.text aussieht (ob da also auch der Teil drin steht, den Du erwartest).
if (Stringlist1 <> NIL) and (Stringlist1.count >0) then
s := StringList1[0]; end; Ein alternativer Zugriff auf StringList[0] mit den Standardeinstellungen der StringList ginge auch so:
Delphi-Quellcode:
--
if StringList1 <> NIL then begin
S := copy (stringlist1.text, 1, pos (sLinebreak, stringlist1.text)-1); end; |
AW: TStringList - Zugriff auf property
Ich würde FastMM einbinden um zu schauen was da nicht in Ordnung ist.
|
AW: TStringList - Zugriff auf property
Zeig doch mal den Sourcecode
Gruß K-H |
AW: TStringList - Zugriff auf property
Danke für alle Antworten.
Ich habe alle Anregungen probiert und einen Screenshot von der Ausgabe im Debug-Fenster gemacht. Ich werde daraus nicht klüger. ![]() Und ja, die Optimierung ist abgeschaltet. Danke für weitere Ideen im voraus! |
AW: TStringList - Zugriff auf property
Zitat:
Wenn der Fehler bei mir läge, wäre mir das deutlich lieber, denn dann könnte ich ihn korrigieren: Var ... SL_SUB: TStringList; ... begin {$O-} SL_SUB:=TStringList.Create; SL_SUB.Clear; ....... SL_SUB.Add(' div zeilen '); ..... SL_SUB.CustomSort(StringListSortComparefn2); * hier ist der Screenshot aus dem debug window genommen * ![]() SL_SUB.Free; end; |
AW: TStringList - Zugriff auf property
Hallo,
aha, wir kommen näher. Es wird also sortiert. "div Zeilen" nützt uns nichts, bitte lauffähigen Code hier reinstellen. SL_SUB.Add('x'); SL_SUB.Add('y'); Es fehlt der Code von StringListSortComparefn2. 1. Was passiert eigentlich, wenn Du StringListSortComparefn2 mal auskommentierst? 2. Hast Du mal einen Brealpoint auf die Zeile SL_SUB.Free; gesetzt und dann deine Watchpoints angesehen. 3. Nimm mal alle anderen Watchpoints raus. |
AW: TStringList - Zugriff auf property
Erstens würde ich wie gesagt FastMM versuchen. Wenn da irgendein Objekt benutzt wird nachdem es schon freigegeben wurde, wird das damit angezeigt. Inklusive Stacktraces wo das Objekt erstellt und wo freigegeben wurde und wo der Fehler nun verursacht wird.
Die andere Variante: Kommentiere immer mehr Teile des Quelltextes aus bis du entweder merkst was den Fehler verursacht, weil er nicht mehr auftritt oder du ein Beispiel hast, das klein genug ist um es komplett zu zeigen. Wenn du den Quelltext nicht veröffentlichen möchtest, kannst du mir auch ein lauffähiges größeres Beispiel per PN schicken. Dann würde ich hier nur posten wo der Fehler herkommt, wenn ich ihn gefunden habe. Heute hätte ich gerade etwas Zeit mir das anzuschauen vorausgesetzt ich bekomme ein Beispiel, mit dem ich den Fehler reproduzieren kann. |
AW: TStringList - Zugriff auf property
Zitat:
Es wird immer seltsamer! Ich habe einen Screenshot von dem Restcode gemacht. ![]() Also ich bin mit meiner Weisheit am Ende. Vor vielen, vielen Jahren hatte ich mal so einen "Fehler". Nach einigen Wochen fand ich dann, dass im interface Teil ein Strichpunkt irregulär war. Doch so etwas sehe ich heute nicht. Oder ein anderes mal, auch lange her... da hatte ich eine Variable, die den Schlusskurs enthielt, "close" genannt (reserviertes Wort). Bin mittlerweile für jegliche innovative Idee offen. Insbesondere, wie man Code aus einem Monsterprojekt, das jahrzehntelang entwickelt wurde und komplex vernetzt ist, zum Debug extrahiert... Ich weiß nur, dass TCheckList Box in meiner Delphi XE 3 Version einen Bug ab Werk hat. Dieser Bug ist ebenfalls ein Listenzugriff. Doch "Schuldzuweisung" nützt mir nichts! Ich muss meinen Code irgendwie zum Laufen bringen. Hat jemand eine Idee, wie ich die Werte, die stimmen, auslesen kann? (womit die Frage wieder bei meinem originalen Posting ist) |
AW: TStringList - Zugriff auf property
Was ist denn jetzt der Fehler? Wir sehen hier nur das "inaccessible value" im Watch-Fenster. Was kommt denn im ShowMessage an?
Ich habe das jetzt hier mal in einem simplen Button-Click mit XE3 nachprogrammiert und da funktioniert sowohl das ShowMessage als auch die Anzeige im Watch-Fenster. Kann es sein, daß du irgendwelche Plugins oder Komponenten installiert hast, die dieses auslösen? Klappt es in einer frischen Delphi-Installation? Passiert das nur bei dieser einen Stringliste SL_SUB oder auch bei anderen? Wie sieht es aus, wenn due SL_SUB umbenennst? |
AW: TStringList - Zugriff auf property
Kann es sein das Du irgendwo Deinen Stack überschreibst?
Stell doch mal Deine lokalen Variablen um also anstatt:
Delphi-Quellcode:
zu so etwas:
var
SL, SL_Waren, SL_SUB, SL_Waren2: TStringList;
Delphi-Quellcode:
Dann kannst Du auch noch die Reihenfolge ändern.
var
SL: TStringList; SL_Waren: TStringList; SL_SUB: TStringList; SL_Waren2: TStringList; Stelle mal Dein SL_SUB an den Anfang
Delphi-Quellcode:
was ist dann?
var
SL_SUB: TStringList; SL: TStringList; SL_Waren: TStringList; SL_Waren2: TStringList; sind alle lokalen Variablen sinnvoll initialisiert? z.B:
Delphi-Quellcode:
begin
// nur als Beispiel SL := nil; SL_Waren := nil; SL_SUB := nil; SL_Waren2 := nil; |
AW: TStringList - Zugriff auf property
Kann mich den Vorrednern nur anschliessen. Habe folgendes in XE3 kopmpiliert und da läuft alles wie es soll.
Code:
procedure TForm1.FormCreate(Sender: TObject);
var SL_SUB: TStringList; Anzahl: Integer; I: Integer; begin {$O-} Anzahl := 10; SL_SUB := TStringList.Create; for I := 0 to Anzahl do begin SL_SUB.Add(IntToStr(I)); end; ShowMessage(SL_SUB.Strings[0]); // In der Watchlist wird mir hier der korrekte Wert '1' angeziegt SL_SUB.Clear; SL_SUB.Free; end; Allerdings solltest du solche Codekonstrukte immer in einen Try/Finally Block packen. Also so:
Code:
procedure TForm1.FormCreate(Sender: TObject);
var SL_SUB: TStringList; Anzahl: Integer; I: Integer; begin {$O-} Anzahl := 10; SL_SUB := TStringList.Create; try for I := 0 to Anzahl do begin SL_SUB.Add(IntToStr(I)); end; ShowMessage(SL_SUB.Strings[0]); SL_SUB.Clear; finally SL_SUB.Free; end; end; |
AW: TStringList - Zugriff auf property
Danke allen hier, die noch Kampfgeist haben!
(dass jemand mit der Zuweisung von "nil" initialisieren will, vergessen wir) Ich habe jetzt das umgesetzt: - das TStringList in einer extra Zeile deklariert - die Var umbenannt von SL_SUB in SL_Untergruppe - try finally benutzt (das "immer" zu tun, kostet zuviel Performance), doch hier war es wirklich ein Ansatzpunkt, der etwas änderte: Ich beobachte zwei Effekte: 1) Die ShowMessage Ausgabe funktioniert auf einmal korrekt(!!), - für beide Testausgabezeilen. 2) Der finally Block wird abgearbeitet. Also ein kleines Quentchen Trost. Doch noch immer crasht mir die komplette IDE, wenn ich meinen Wert weiterverarbeiten möchte. Und noch immer sehen die Werte irritierend aus. Wieder sagt ein Bild mehr als 1000 Worte. ![]() |
AW: TStringList - Zugriff auf property
ok das nil war als Beispiel ungünstig gewählt,
mir ging es darum dass Deine lokalen Variablen die ja auf dem Stack liegen erst mal initialisiert sind. Initialisiert in dem Sinn nicht mit dem Inhalt des Stacks sondern klar definiert. Und da zählt auch Nil dazu.. ;-) Da Du aber ja immer nur Bilder zeigst, ohne den ganzen Sourceblock......... Ich behaupte immer noch das Du irgendwo den Inhalt des Stack überschreibst... Mach mal Spasseshalber zwischen Deine lokalen Variablen jeweils ein Dummy z.B:
Delphi-Quellcode:
Initialisieren
var
SL: TStringList; Dummy1 : int64; SL_Waren: TStringList; Dummy2 : int64; SL_SUB: TStringList; Dummy3 : int64; SL_Waren2: TStringList; Dummy4 : int64;
Delphi-Quellcode:
So solltest Du eventuell an diesen Variablen im Debugger etwas sehen...
begin
Dummy1 :=0; Dummy2 :=0; Dummy3:=0; Dummy4:=0; end; |
AW: TStringList - Zugriff auf property
Zitat:
dann machst du etwas falsch. Das Risiko try-finally nicht zu benutzen ist ein vielfaches höher als das Quäntchen "Performance" was dir verloren geht. Was deinen Code angeht wäre es glaube ich jetzt ganz gut wenn wir einen größeren Überblick über den Code hätten. So wie es aussieht liegt der Fehler tiefer. Falls möglich wäre es am besten wenn du deinen ganzen Code mal hochladen würdest. |
AW: TStringList - Zugriff auf property
an Michael, danke für Deine Antwort,zu "ganzen Code hochladen": Du sprichst von einer ziemlich großen eingebundenen DB und deutlich über 100 Units.
Eine "einfache Version" an Code siehst Du bereits, den ganzen Code willst Du, glaube mir, NICHT sehen, smile. Wenn Du die umfangreichen DB-Query-Abfragen noch in stochastische Prozesse schickst, dann merkst Du ein "try" mehr oder weniger auch dann, wenn Du so einen schnellen Computer hast wie ich. Alte PCs haben da noch tagelang gerechnet daran. Fritz, ad Deklarationszeilen einschieben: leider nein, da sehe ich diesmal nichts Neues. ![]() Dass etwas Gröberes schief läuft im Speicher, das ist klar. Mit "Überschreiben" wird es schon etwas haben, doch was? Es sieht alles regulär aus. Ein Kollege hier (danke!) ließ das ja durchlaufen und es klappte. Bei mir klappt es nicht. Es muss etwas sein, das entweder in meinem Code passiert oder in XE 3 oder in dem Zusammenspiel der beiden. Bist Du gut in Assembler? Ich leider ganz schlecht, doch man müsste, wenn man weiß wie, die Speicherzugriffe auswerten können, die intern schief laufen. Oder durch die interne Delphi Unit surfen. Allerdings fürchte ich, dass ich da stundenlang klicke und der Fehler im Grunde an anderer Stelle passiert, als ich denke. Weil ich nur auf die Auswirkugen davon klicken würde. |
AW: TStringList - Zugriff auf property
Hallo Nicole,
ok, klingt alles schwierig. DataBreakpoints sagen Dir etwas? Die könnten helfen, oder bau Dir ein Logging ein. Ein hilfsvariable Pointer auf Deine SL_SUB; Nach jedem Aufruf versuche den Inhalt von z.B SL_SUB[0] zu loggen; // Pseudocode Sowas wie Loger (Pointer Helper, Pointer SL_SUB, Inhalt SL_SUB[0]); Kanst mir auch ne PM schicken. |
AW: TStringList - Zugriff auf property
Hallo!
Probier doch mal eine Ableitung von TStringlist zu machen und dann in diesem Destroy einen Haltepunkt. Und SL_SUB ist dann von deinem TMyStringlist Dann solltest du erkennen können ob dein Stringlist irgendwo zerstört wird.. Gruß Günter |
AW: TStringList - Zugriff auf property
Zitat:
Tritt das Problem auf allen PC's auf oder nur auf Deinem? Welche Windows-Version? Innerhalb oder außerhalb einer VM? - Versuche einmal das Programm ohne den Style auszuführen - Setze das {$O-} einmal vor die Prozedure, statt innerhalb (ist eigentlich egal, versuchs trotzdem mal) |
AW: TStringList - Zugriff auf property
Hallo,
also, neues Projekt anlegen, FormCreate erzeugen und Deinen Code reinkopieren und laufen lassen. Was passiert denn dann? Nennt sich Minimalbeispiel. Hast Du mal FastMM4 eingebunden? |
AW: TStringList - Zugriff auf property
Ich bin mir relativ sicher, dass das was du hier siehst ein Nebeneffekt von was ganz Anderem ist, das vermutlich den Speicher des Debuggers zerschossen hat.
Wie schon mehrfach erwähnt, baue mal ein simples Projekt mit nur einem FormCreate (wie in meinem Beispiel) und debugge das. Wenn da alles IO ist, suchst du an der falschen Stelle. Dann machst du zu 100% irgendwo sonst den Speicher "kaputt" und das was du hier siehst sind alles Nebeneffekte davon. Betreffs Try/Finaly: Wenn du das nicht richtig genutzt hast, würde es mich nicht wundern, wenn ganau darin der Hund begraben ist. Wenn du das nicht gerade in einem Loop mit 1 Mio. Durchläufen platziert hast, wirst du keinen nennenswerten Performanceunterschied merken. Ansonsten platziert man es ausserhalb des Loops. Aber einfach darauf verzichten ist das dümmste was man machen kannst. |
AW: TStringList - Zugriff auf property
Geht es eigentlich immer noch um den Inaccessable Value?
Wenn Ja -
Delphi-Quellcode:
bringt wohl jeden Debugger aus dem Tritt.
(showmessage(sl_untergruppe[2]);
Ansonsten vergesst es. Gruß K-H |
AW: TStringList - Zugriff auf property
Zitat:
Und da wir den Code nicht sehen können, glaube ich nicht, dass man hier den Fehler finden kann. PS: @NicoleWagner, sind dir die kleinen Symbole über dem Eingabefeld aufgefallen, in dem du deine Antworten schreibst? Diese sind ganz nützlich ;-) Helfen sie doch z.B. Delphi-Code zu formatieren. Und etwas weiter unten findest du einen Button "Anhänge verwalten". Damit kann man Bilder hochzuladen, dann müssen die Leser nicht zur Dropbox wechseln. |
AW: TStringList - Zugriff auf property
Die Lösung:
Einmal danke allen, die hier mitgeraten haben. Viele hatten auch recht mit ihren Ideen. Die konkrete Methode, wie ich an den Fehler rankomme, kam jedoch von Fritz (danke!) via Mail. Fritz' Idee war, dass ich das BEFÜLLEN des TStringLists in eine eigene Methode auslagere. Als ich die geschrieben hatte und zeilenweise durchklickte, fand ich den Wurm: Mein StringList wird durch andere StringLists befüllt. Ein sortiertes kommt von links, ein anders sortiertes kommt von rechts. Was mir entging: Es gibt Sonderfälle, in denen eines dieser Quell-StringLists eine Zeile weniger hat. Sah alles ganz normal aus. Das Zielstringlist wurde übergeben und auch in der Werteliste zeigten sich Inhalte, - die jedoch im Einzelfall gar nicht da waren (das errieten hier viele). Wo mir der Fehler als 'aufgetreten' angezeigt wurde, da war er nicht zu finden, weil schon lange vorher als Sand im Getriebe. Mein Weg zu besserem Code sieht jetzt so aus: Statt ZielStringList.Add(Quellstringlist[zugriff]); fülle ich jetzt mit If Quellstringlist.Count > zugriff then ZielStringList.Add(Quellstringlist[zugriff]); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05: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