Autor Beitrag
Wolff68
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: So 19.10.03 23:07 
Hallo. Hab hier gerade ein verblüffendes Phenomen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
...
  public
    { Public-Deklarationen }
    s1 : String;
    s2 : PChar;
...

procedure TForm1.Button1Click(Sender: TObject);
begin
  s1 := '123456789'
  s2 := @s1[2]; //s2 = s1 ohne erstes Zeichen, und ohne dabei s1 zu kopieren
  Edit2.Text := s2;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  s1 := '1234567890'
  Edit2.Text := s2;
end;


Ich starte das Programm und klicke auf Button1 und Edit2.Text = '23456789'. Wie gewollt also.

Nun drücke ich auf Button2 und bekomm Edit2.Text = '2345678' !!!!
Drücke ich nochmal Button2 bekomm ich Edit2.Text = '234567890' !!!
Nochmal Button2 hab ich wieder '2345678' uns so weiter. Immer abwechselnd... :nut:

Kapiert das hier jemand?

_________________
"Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
MSCH
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: Mo 20.10.03 11:22 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.Button2Click(Sender: TObject); 
begin 
  s1 := '1234567890';  
  Edit2.Text := s2; 
end;


wo wird hier S2 zugewiesen?grez
msch

_________________
ist das politisch, wenn ich linksdrehenden Joghurt haben möchte?
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mo 20.10.03 11:48 
So.. ich hab mir das mal in einem Test-Programm angeschaut. Nachdem Button1 geklickt wurde schaut noch alles ganz nett aus: s1 hat die Adresse $BF3EAC und s2 hat die Adresse $BF3EAD, also alles wie es sein sollte.
In Button2-Click, nach der Zuweisung von '1234567890' zu s1, hat s1 jedoch auf einmal die Adresse $BF3EC4, s2 jedoch immer noch die Adresse $BF3EAD. Woran liegt das nun? Die Antwort findet man wenn man sich mal anschaut was hinter dieser simplen String-Zuweisung wirklich steckt.

Intern wird bei jeder String-Zuweisung die procedure "_LStrAsg" aufgerufen. Je nachdem ob es sich bei dem zugewiesenen String um eine String-Variable oder eine Konstante handelt wird dann entweder nur der Zeiger neu gesetzt und der Referenzzähler gesetzt, oder aber die procedure "_NewAnsiString" aufgerufen, welche neuen Speicher reserviert, den String dort hineinkopiert und den Referenzzähler des neuen Strings auf 1 setzt. Der Speicher auf den der String vorher verwiesen hat wird jedoch in jedem Fall freigegeben.

Was bedeutet das nun für deinen konkreten Fall:
du weißt der Variable s1 einen Konstanten Wert zu, dh. für s1 wird neuer Speicher reserviert, der neue String hineingeschrieben und der alte Speicher freigegeben. s2 verweißt damit praktisch auf den freigegebenen Speicher. Bei erneutem Aufruf beginnt das ganze Spielchen von vorne, der Speicher für s1 wird also wieder neu reserviert, kopiert etc - _aber_ der Speichermanager von Delphi legt jetzt die alte Adresse (wo vorher der Speicher freigegeben wurde) als neue Adresse fest wo der neue Speicher reserviert wird. Es wird also praktisch bei jedem Button-Click der Inhalt von s1 von einer Adresse an eine andere verschoben, wobei es sich im Prinzip nur um 2 Adressen handelt zwischen denen s1 immer hin und her geschoben wird.

Also immer wenn s1 auf seine urspüngliche Adresse verschoben wird steht in s2 '234567890' und immer dann wenn s1 eine andere Adresse hat steht in s2 '2345678', wobei es aber auch durchaus passieren kann, dass in s2 nur "Datenmüll" landet, da ja s2 auf freigegebenen Speicher verweißt!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Wolff68 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: Mo 20.10.03 21:00 
Ahaaa. Danke für die ausführliche Erklärung Motzi! :dance:

Aber Du sprichst hier immer nur 'konstante' Werte an.
Ich hatte allerdings den gleichen Effekt, als ich s1 := Edit1.Text; gemacht hatte.
Entweder verhält sich also Edit1.Text in diesem Fall wie eine Konstante, oder es gilt auch für variable Typen.

Nun gut. War ein Testprogramm, und eigentlich brauch ich nur EINE Zuweisung, ohne Ändern des Ursprungs.
Wollte mit dem Ändern eigentlich nur sehen, ob die Zuweisung klappt.
(@MSCH: Das ist ja der Sinn der Sache. Daß beide auf die gleiche Speicherstelle gehen)

In meinem Fall benötige ich sowieso nur die erste Zuweisung ohne Änderung des Ursprunges.

Super. Danke nochmal.

_________________
"Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 21.10.03 14:05 
Wolff68 hat folgendes geschrieben:
Ich hatte allerdings den gleichen Effekt, als ich s1 := Edit1.Text; gemacht hatte.

Das liegt daran, dass TEdit.Text eine Get-Methode besitzt, die per WM_GETTEXT den Inhalt des Edits holt, nur wird dazu jedesmal eine neue String-Variable angelegt und diese wird dann eben s1 zugewiesen. Und dadurch, dass jedesmal eine neue Variable angelegt wird endet es mit demselben Ergebnis wie vorher - der String wird im Prinzip immer zwischen den 2 Adressen "verschoben".

Wenn du das ganze mit einer Variable machst passiert das nicht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
...
  public
    { Public-Deklarationen }
    s: String;
    s1 : String;
    s2 : PChar;
...

procedure TForm1.Button1Click(Sender: TObject);
begin
  s1 := '123456789'
  s2 := @s1[2]; //s2 = s1 ohne erstes Zeichen, und ohne dabei s1 zu kopieren
  Edit2.Text := s2;
  s := '1234567890';
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  s1 := s; 
  Edit2.Text := s2;
end;

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!