BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

String assignment behavior

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi ObjectPascal
View previous topic :: View next topic  
Author Message
James Jones
Guest





PostPosted: Fri Aug 27, 2004 5:25 pm    Post subject: String assignment behavior Reply with quote



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





PostPosted: Tue Aug 31, 2004 12:50 am    Post subject: Re: String assignment behavior Reply with quote



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)) - Cool^);
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 Smile 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
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi ObjectPascal All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.