Autor Beitrag
Born-to-Frag
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: Mo 30.10.06 00:05 
Hallo!

Ich habe ein kleines Problem.
Folgender Code funktioniert:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button1Click(Sender: TObject);
var
  x: string;
begin                                     
  x := 'blah'; 
  listbox1.Items.AddObject('r', tobject(x));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  showmessage(string(listbox1.Items.Objects[0]));
end;


So funktioniert es nicht mehr:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Button1Click(Sender: TObject);
var
  x: string;
begin                                     
  x := 'blah';  
  x := copy(x, 1, 3);
  listbox1.Items.AddObject('r', tobject(x));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  showmessage(string(listbox1.Items.Objects[0]));
end;


Warum?


greetz

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Coder
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1383
Erhaltene Danke: 1

WinXP
D2005 PE
BeitragVerfasst: Mo 30.10.06 18:44 
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:
type
  TMeinString = class(TObject)
    Text: String;
  end;

...

var
  ...
  x: TMeinString;

...

procedure TForm1.Button1Click(Sender: TObject);
begin
  x := TMeinString.Create;
  x.Text := 'blah';
  x.Text := copy(x.Text, 1, 3);
  listbox1.Items.AddObject('r', x);
end;


procedure TForm1.Button2Click(Sender: TObject);
begin
  showmessage(TMeinString(listbox1.Items.Objects[0]).Text);
end;

procedure TForm1.FormClose(Sender: TObject);
begin
  x.Free;
end;


Einen einfacheren Weg kenn ich leider auch nicht.

MfG
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 30.10.06 19:13 
Moin!

@user profile iconBorn-to-Frag: Der Typecast von String auf TObject ist aber auch wirklich unschön <brrr> :? ;)

@user profile iconCoder: Ich glaube, es ging nicht um eine Alternative (schätze, das hätte BtF auch noch hingekriegt ;)), sondern vielmehr um das WARUM bei dem Code oben.

Tja, ich hätte auch gesagt, dass müßte gehen - tut´s aber nicht. Und ich wüßte wohl auch gerne mal warum... :gruebel:

user profile iconBenBE, hast du nicht eine Idee? :D

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Coder
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1383
Erhaltene Danke: 1

WinXP
D2005 PE
BeitragVerfasst: Mo 30.10.06 19:21 
user profile iconNarses hat folgendes geschrieben:
@user profile iconCoder: Ich glaube, es ging nicht um eine Alternative (schätze, das hätte BtF auch noch hingekriegt ;)), sondern vielmehr um das WARUM bei dem Code oben.
Wieso sagt er dann?
user profile iconBorn-to-Frag hat folgendes geschrieben:
Ich habe ein kleines Problem.


Wenn man den String vorher noch bearbeitet funktioniert es nicht :gruebel: komisch...
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: Mo 30.10.06 21:13 
@Narses: Wie soll ich es denn sonst machen?

Ich habs jetzt übergangsweise so gelöst, damit ich mit dem Projekt überhaupt weiter machen kann, ist aber genauso "ünschön" :D

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  Text: PString;
begin
  New(Text);
  Text^ := Copy(.., .., ..);
  ListBox1.Items.AddObject('Test', TObject(Text));
end;

//Zum freigeben später irgendwo Dispose(.Items.Objects[i])


Achja was ich vielleicht noch sagen sollte: Wenn man das ShowMessage noch in die gleiche Prozedur verschiebt in dem ich den Text in die ListBox einfüge, wird es richtig angezeigt (beim nicht funktionierendem Code)..


EDIT: Mich hätte das Problem vielleicht weniger verwundert, wenn die DelphiHilfe nicht soetwas geschrieben hätte:
Die Delphi-Hilfe hat folgendes geschrieben:
S ist ein Ausdruck des Typs String oder dynamisches Array. Index und Count sind Integer-Ausdrücke. Copy gibt einen Teilstring oder ein Teilarray zurück, das Count Zeichen oder Elemente ab S[Index] enthält. Der Teilsstring oder das Teilarray ist eine eindeutige Kopie (d.h., Speicher wird nicht gemeinsam mit S genutzt, obwohl Zeiger- oder Objekt-Elemente des Arrays nicht kopiert werden).


PS: Wie sieht's mit dem gehighlightetem aus, liegts daran?

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.


Zuletzt bearbeitet von Born-to-Frag am Mo 30.10.06 21:21, insgesamt 2-mal bearbeitet
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Mo 30.10.06 21:18 
*g* ich hatte es grad mit PChars versucht. Funktioniert auch fast. Aber ich denke mal, dass du hier einfach nur über Pointer gehen kannst, wenn du zuverlässige Ergebnisse willst. Der Hintergrund wäre natürlich noch interessant zu erfahren :D

Gruß alias5000

_________________
Programmers never die, they just GOSUB without RETURN
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 30.10.06 22:25 
Moin!

Ich vermute den Zusammenhang in den String-Descriptoren. Aber wie gesagt, wissen tu ich´s auch nicht. :? :|

@user profile iconBorn-to-Frag: Ich hätte ein record mit einem Element (dem String) genommen und das mit New() und Dispose() gemacht. ;) So erzeugst du auf jeden Fall einen neuen Descriptor. :D

//EDIT: Noch eine Alternative: eine Stringliste indexsynchron dazu halten. ;) Oder falls das zu aufwändig ist: Eine Stringliste für die zugeordneten Strings anlegen und den Index als TObject in der Listbox ablegen, dann biste indexwahlfrei in die Stringliste. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Mo 30.10.06 23:19 
ausblenden Delphi-Quelltext
1:
2:
//So gehts:
  SL.AddObject('esfse', TObject(PChar(x)));
Ich nehme an, dass er so nicht den Speicher verwirft, bin mir da aber wirklich nicht sicher!

Gruß Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Di 31.10.06 02:46 
Geht der Coder-Code ? (echt Klasse Nick für Programmierforum :lol: ) Es geht mir um sowas :

ausblenden Delphi-Quelltext
1:
2:
3:
  TMeinObject = class(TObject)
// ... Daten
  end;


Bei mir sieht das ähnlich wie bei einem Record aus. Konkret : 3 bools, 1 integer, 1 eigener Typ, 1 Tcolor. Das sind die "Daten". Warum soll das mit strings nicht auch gehen ? Man könnte auch ein TImage noch reinpacken. Damit könnte zwar die Listbox selber nichts anfangen. Aber es wäre z.B. durchaus möglich beim Klicken auf eine Listbox irgendwo das nur diesem Item zugeordnete Bild anzuzeigen. Wo ist eigentlich das Create von Deinem eigenen TObject ? :shock: Bei Coder war da was zu sehen.

Jetzt noch was zu dem TObject in diesem Zusammenhang : ich benutze das bei Stringgrids, das ist noch komlizierter weil 2-dimensional. Könnte schon ein Unterschied sein. Das glaube ich aber aus folgendem Grund nicht (und es war verdammt viel Arbeit, sich alle Infos die noch kommen einzeln zusammenzusuchen !) : mit dem Typ TStrings wurde die Eigenschaft Objects eingeführt. Die gilt dann ja auch für die Nachfolger. TStringlist bis zum Stringgrid usw. Ne Menge Typen können das. Und siehe an : die Items der Listbox sind ja auch TStrings ! Wer hätte das geahnt. :mrgreen: Also gilt tatsächlich alles auch für die Listbox.

Jetzt gibt es aber ein Problem : die Objects sollen ja alles mögliche enthalten können. Baue doch mal einer eine Listbox, die je nach angeklickter Zeile ein Liedchen abspielt. Das geht auch ! Was soll nun aber die arme Listbox damit anfangen ? Das kann sie nur deshalb, weil sie in Form der Objects die Möglichkeit hat, quasi per Zeiger auf beliebige verbundenen Daten zuzugreifen. So, der Haken ist eben jetzt, daß die Listbox nur sehr lose mit dem anderen Krempel gekoppelt ist. Im Klartext heißt das : Listbox da, dann sind die Objects noch lange nicht da und Listbox weg, dann sind die Objects ohne eigene Maßnahmen noch lange da. 8)

Noch kurz zurück zur konkreten Frage : ich glaube man darf auf ein TObject nicht direkt zugreifen, geschweige denn noch zu versuchen, damit eine Typumwandlung zu machen, sondern nur auf eine eigene class, die davon abgeleitet ist bzw. in diesem Fall auf Listbox1.Item.Objects [??] :gruebel: Weiß jetzt auch nicht mehr genau. Bevor ich jetzt aber noch 2 Units mit 3000 Zeilen durchwühle : mache das mal selber noch intensiver mit der Hilfe. Das Zitat daraus paßt IMHO so nicht in den Kontext.

_________________
Gruß
Hansa
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Di 31.10.06 09:34 
Hallo!

Also, wieso das nicht klappen kann ist ja eigentlich klar. Du hast eine lokale Variable vom Typ String, für die wird Speicher reserviert. Im Endeffekt ist String ja auch nur ein Zeiger auf eine Zeichenkette. Sobald die Prozedur aber beendet ist, geht die String-Variable ja out of scope, der Speicherbereich für den String wird vom Programm freigegeben. Wenn du dann dir noch die Position der Speicherkette kopierst(eben deine Pointer-Operation), zeigst du nun auf einen ungültigen Speicherbereich, der vielleicht auch schon durch andere Codeteile wieder überschrieben wird.

Das es mal klappt, mal nicht, ist wohl reiner Zufall. Delphi gibt den Speicher eben nicht sofort wieder ans Betriebssystem zurück, deshalb kommt wohl manchmal keine Accessviolation.

Cu,
Udontknow
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 31.10.06 10:56 
Moin!

@user profile iconhansa: :gruebel: Hää?! :nixweiss:

@user profile iconUdontknow: Stimmt, hatte gar nicht bemerkt, dass user profile iconBorn-to-Frag lokale Variablen verwendet hat... :autsch: Von Wäldern und Bäumen... :roll: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: Di 31.10.06 17:45 
Nene, wenn ich
ausblenden Delphi-Quelltext
1:
ListBox1.Items.AddObject('blah', TObject(Copy(.., .., ..));					

mache, funktioniert das genauso wenig (Anfangs hatte ich es so) :( ohne Copy kann ich auch lokale Variablen hinzufügen.

@Hansa: Ich verstehe nicht was du damit sagen willst :D Natürlich kann ich Strings als TObject adden, es geht mir darum, dass es nach dem Copy()-Befehl nicht mehr geht ;) und PChar() hab ich auch schon versucht :?

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 31.10.06 18:05 
Moin!

user profile iconBorn-to-Frag hat folgendes geschrieben:
Nene, wenn ich
ausblenden Delphi-Quelltext
1:
ListBox1.Items.AddObject('blah', TObject(Copy(.., .., ..));					

mache, funktioniert das genauso wenig (Anfangs hatte ich es so) :(

Ja, denn da ist das Ergebnis von Copy() ja "noch lokaler", nämlich nur für diesen Aufruf. ;)

user profile iconBorn-to-Frag hat folgendes geschrieben:
ohne Copy kann ich auch lokale Variablen hinzufügen.

Was aber, wie user profile iconUdontknow bereits so schön treffend erkannt hat, nur dann funktioniert, wenn der Speicher, der an dem Zeiger hängt, nicht "wiederverwertet" wird. Wenn du mit dieser "unschönen" String-casterei tatsächlich "leben" willst, dann mußt du dafür sorgen, dass die entsprechenden Strings für die gesamte Gültigkeitsdauer auch auf dem Heap reserviert bleiben. Das geht aber nur automatisch mit dem Referenzzähler im String-Descriptor - und den hast du nicht mehr, wenn du den String auf einen Pointer "reduzierst". Fazit: das ganz ist IMHO "unsauber" und du solltest besser mit einer Alternative arbeiten. :mahn: ;)

user profile iconBorn-to-Frag hat folgendes geschrieben:
@Hansa: Ich verstehe nicht was du damit sagen willst :D

;) Beruhigt mich, dass du user profile iconhansa auch nicht verstehst... :D

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: Di 31.10.06 18:08 
Achso ok alles klar :zustimm:

Dann mach ich es mit PString oder eben mit ner StringList :)

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Di 31.10.06 19:04 
user profile iconBorn-to-Frag hat folgendes geschrieben:
Achso ok alles klar :zustimm:

Dann mach ich es mit PString oder eben mit ner StringList :)
PString? Was soll das denn sein? Machst doch mit einem PChar und StrPCopy!
Das ganze halt initialisieren mit New (GetMem) und wieder freigeben Dispose (FreeMem).

Gruß Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Di 31.10.06 19:18 
user profile iconNarses hat folgendes geschrieben:
;) Beruhigt mich, dass du hansa auch nicht verstehst... :D


Dann kaufe dir was dafür und schenke es am besten dem, der auch nichts versteht. Dann seid ihr beide eventuell kurzfristig glücklich. :lol: Danach wirds wohl wieder krachen im Speicher. :mrgreen:

Das Problem liegt darin, zu wissen, wie man die Objects-Eigenschaft richtig benutzt. Tauchen schon solche Diskussionen auf mit "eventuell wird da irgendwo der Speicher nicht freigegeben, weiß aber nichts genaues", was soll denn das im Endeffekt werden ? :shock:

Wahrscheinlich ist der Thread sowieso bald erledigt, weil es irgendwie gelingt, in einer bestimmten Konstellation, den Fehler einige Tage nicht zu sehen. 8)

Sollte allerdings konkreter Bedarf bestehen, die Objects wirklich richtig einzusetzen, dann bitte ich um PN mit kurzer Beschreibung, um was es geht. Wer mit OOP nichts anfangen kann, für den lohnt sich das Ganze aber sowieso nicht ! Eventuell mache ich bei Bedarf dann ein Tutorial darüber. Das Borland Marketing ist anscheinend zu blöd, solche mächtigen Sachen etwas publik zu machen.

_________________
Gruß
Hansa
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 31.10.06 20:40 
Hier wurde ja schon recht viel geschrieben ... teilweise stimmt's sogar ... Bin aber auf Grund des Umfangs dieses Threads nicht dazu gekommen, alles zu lesen ...

Aber zur Erklärung, warum die Variante mit String nicht geht, aber PString und über Klassen.

Kurz: Es hat mit den Zeigern zu tun.

Langfassung (für die, die's Interessiert):
Wenn man eine Stringkonstante zuweist, so wird diese einfach nur kopiert und deren Referenzzähler um 1 erhöht. Bei Strings, die direkt im Source gespeichert sind, ist dieser Zähler generel -1, d.h. dass sie nicht gezählt werden. Wendet man nun eine Routine wie Copy auf einen String an, so wird ein neuer String erzeugt, der natürlich auch eine neue Adresse hat. Dieser String wird nun aber auf jeden Fall referenzgezählt, da er zur Laufzeit erzeugt wurde und damit auch wieder freigegeben werden muss. Das Freigeben eines Strings erfolgt dabei immer am Ende des Gültigkeitsblocks - in diesem Fall am Ende der Routine.

Nun aber noch zum Unterschied zwischen TObject(String) und TObject(PString):
String ist einfach nur ein Pointer auf das erste Zeichen des Strings. Ändert sich die Lage des Strings im Speicher, wird dieser einfach geändert. Kopiert man nun mit TObject(String) diesen in eine TStringList, so wird die Adresse bei Änderungen am String nicht geändert, zeigt also auf den alten Speicherplatz.
Nimmt man aber einen PString, so speichert man nicht die Adresse des ersten Zeichens des Strings, sondern die Position, an der im Speicher diese Adresse zu finden ist. Somit wird bei einem Update der String-Adresse diese auch "geändert".
Ferner legt PString die interne Referenzzählung von Delphi dahingehend flach, dass Referenzen immer dann als gelöscht zählen, wenn dies eine normale String-Operation tun würde ODER der Pointer auf den String freigegeben wird. Beides ist im PString-Beispiel nicht der Fall --> Der String bleibt erhalten.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Born-to-Frag Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: Di 31.10.06 21:57 
Danke für die Erklärung, BenBe.

Ich war verwirrt, weil ich wohl immer dachte, dass
ausblenden Delphi-Quelltext
1:
2:
3:
x := 'blah';
//Zu vergleichen sei mit
x := ReturnBlah; //irgendeine Funktion halt

Eben dass neuer Speicher dafür reserviert wird :oops:

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 01.11.06 00:01 
Moin!

@user profile iconBenBE: Danke! ;)

@user profile iconhansa: Falls es dir noch nicht aufgefallen ist: das Problem ist gelöst. Spannend also, welches "Geheimwissen" du da per PN "entweihen" willst... :gruebel: und vor allem: bloß nicht hier! Nachher kann da noch einer was mit anfangen... :P

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 01.11.06 01:50 
user profile iconNarses hat folgendes geschrieben:
@hansa: Falls es dir noch nicht aufgefallen ist: das Problem ist gelöst. ...welches "Geheimwissen" du da per PN...


Du redest Blödsinn. Geheimwissen ? :shock: Das ist alles überall nachzulesen. Aber eben nicht so im Zusammenhang, wie in einem eventuell geplanten Tutorial.

_________________
Gruß
Hansa