 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
James Jones Guest
|
Posted: Fri Aug 27, 2004 5:25 pm Post subject: String assignment behavior |
|
|
Hi all,
I've come across a situation that puzzles me quite a bit. Here how to
reproduce it in Delphi 7, build 8.1:
Start a new project and put this declaration in a form public area:
String1: string;
Create a button and in it's onclick handler, put the following:
Var
String2: string;
p1,p2: pchar;
begin
// set the string
String1 := 'James' + #9 + 'Jones';
// this should COPY string1 to string2, right?
String2 := String1;
// get a pchar from String2
P1 := pchar(String2);
// find the tab character
P2 := strscan(P1,#9);
// replace the tab with zero
P2^ := #0;
end;
The strange behavior I'm noticing is that the P2^ := #0; assignment
changes both String2 AND String1. How can that be?
A fix for the above code would be to replace the String2 := String1
assignment with:
String2 := DupeString ( String1, 1 );
This fixes the behavior I noted.
Is it possible that somehow String1 is passed by reference insteand than
by value? If so, my (object) pascal understanding is pretty deficient despite
the fact that I've been at it since Delphi 1 and college!
If any of you guys can explain some of this to me I'd be most appreciative.
Thanks,
James
PS: Strange behavior #2:
Place the String1: String; definition in the Var section of the button onclick
handler and the P2^ := #0; assign will cause an error. Anyone?
PPS: I hope this was the correct group to post to.
|
|
| Back to top |
|
 |
Ed Guest
|
Posted: Tue Aug 31, 2004 12:50 am Post subject: Re: String assignment behavior |
|
|
James Jones wrote:
| Quote: | The strange behavior I'm noticing is that the P2^ := #0; assignment
changes both String2 AND String1. How can that be?
|
Remember that pascal strings are reference counted. A negative offset
of 8 bytes from the start of the string gives the 4 byte reference
count and a 4 byte offset from the start of the string gives the 4
byte size. In your example assigning string2 to string1 results in
both variables pointing to the same string with a reference count of
2. The compiler only makes a copy whenever the variable string2 is
next modified - so called copy-on-write. The modified onclick handler
below shows the differing addresses. Aplogies for the nested
functions, but I tried to make it 'pasteable' into an onclick handler:
procedure TForm1.Button1Click(Sender: TObject);
function GetStringRefCount(const AString: String): Integer;
begin
Result := 0;
if Assigned(Pointer(AString)) then
Result := Integer(Pointer(Integer(Pointer(AString)) - ^);
end;
function GetStringSize(const AString: String): Integer;
begin
Result := 0;
if Assigned(Pointer(AString)) then
Result := Integer(Pointer(Integer(Pointer(AString)) - 4)^);
end;
procedure ShowStats(const AString:String);
var
Size: Integer; Ref: Integer;
begin
Size := GetStringSize(AString);
Ref := GetStringRefCount(AString);
Showmessage(Format('Address : %p | RefCount : %d | Size :
%d',[Pointer(AString),Ref,Size]));
end;
Var
String2: string; p1,p2: pchar;achar: char;
begin
// set the string
String1 := 'James' + #9 + 'Jones';
// this should COPY string1 to string2, right?
String2 := String1;
ShowStats(String1);
ShowStats(String2);
// get a pchar from String2
P1 := pchar(String2);
// find the tab character
P2 := strscan(P1,#9);
// replace the tab with zero
P2^ := #0;
String2 := Trim(String2) + ' a bit more';
ShowStats(String1);
ShowStats(String2);
end;
Note that the strings are passed as const, otherwise new references
are created and the reference count reported is not correct.
| Quote: | String2 := DupeString ( String1, 1 );
|
I never knew there was a DupeString function!!! I learned something
new today DupeString allocate memory for a new string.
| Quote: | PS: Strange behavior #2:
Place the String1: String; definition in the Var section of the button onclick
handler and the P2^ := #0; assign will cause an error. Anyone?
|
Change the handler I posted above and watch the addresses of the
variables. The first example allocates string1 to the heap (since
it's global data) and the second version allocates to the stack. I'll
wager that when you modify the p2 pchar you damage the stack and cause
the AVs, although I can't quite convince myself how :- You might
need someone with a bit more in-depth knowledge to explain that fully.
HTH,
Ed
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|