Board index » delphi » TStringList objects

TStringList objects

Hello,

Does the method Delete for removing item from the string list takes care of
releasing the place of the Objetc in the list ??

thanks,
Bashan.

 

Re:TStringList objects


My understanding of this is no - if you create it you must destroy it.
Delete will free the space used for the pointer (which is all that is stored
in the string list) but not the object itself..  Consider that the objects
might be pre-existing  (edit boxes or labels or buttons on your form, for
example).  You wouldn't those deleted just because you removed the reference
from your list.
_________________________
Gary
http://www.delphiforfun.org
_________________________

Quote
"guy bashan" <bashan...@hotmail.com> wrote in message

news:39f486c3@news.bezeqint.net...
Quote
> Hello,

> Does the method Delete for removing item from the string list takes care
of
> releasing the place of the Objetc in the list ??

> thanks,
> Bashan.

Re:TStringList objects


The answer is emphatically -no- despite what the Delphi documentation
might inadvertantly imply.  None of the list-objects free any of the
objects attached to them.  (And if you think about it, in the general
case you probably would not want them to.)

This gives rise to procedures like this one:

        procedure DetonateExplosivesBeneath(var s: TStringList);
        var n: integer;
        begin
          if s = nil then exit;
          try
            for n := 0 to s.Count - 1 do s.objects[n].free;
          finally
            s.free;
            s := nil;   {my eternal habit to do this}
          end;
        end;

Notice this routine is written slightly more elaborately than it could
be.  But it is, except for the fanciful name, essentially what I use.

Quote
>guy bashan wrote:

> Hello,

> Does the method Delete for removing item from the string list takes care of
> releasing the place of the Objetc in the list ??

------------------------------------------------------------------
Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
mailto:i...@sundialservices.com  (PGP public key available.)
Quote
> Fast(!), automatic table-repair with two clicks of the mouse!
> ChimneySweep(R):  "Click click, it's fixed!" {tm}
> http://www.sundialservices.com/products/chimneysweep

Re:TStringList objects


Hello

Does that mean this the code,
var
  j : integer;
  SL : tStringList;
begin
SL := tstringlist.create(self);
for j := 1 to 1000 do
SL.items.add(inttostr(j));
SL.clear;
SL.free;
SL := nil;
end;

leaves 1000 strings floating in memory without being "freed"?

Quote
Sundial Services wrote:
> The answer is emphatically -no- despite what the Delphi documentation
> might inadvertantly imply.  None of the list-objects free any of the
> objects attached to them.  (And if you think about it, in the general
> case you probably would not want them to.)

> This gives rise to procedures like this one:

>         procedure DetonateExplosivesBeneath(var s: TStringList);
>         var n: integer;
>         begin
>           if s = nil then exit;
>           try
>             for n := 0 to s.Count - 1 do s.objects[n].free;
>           finally
>             s.free;
>             s := nil;   {my eternal habit to do this}
>           end;
>         end;

> Notice this routine is written slightly more elaborately than it could
> be.  But it is, except for the fanciful name, essentially what I use.

> >guy bashan wrote:

> > Hello,

> > Does the method Delete for removing item from the string list takes care of
> > releasing the place of the Objetc in the list ??

> ------------------------------------------------------------------
> Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
> mailto:i...@sundialservices.com  (PGP public key available.)
> > Fast(!), automatic table-repair with two clicks of the mouse!
> > ChimneySweep(R):  "Click click, it's fixed!" {tm}
> > http://www.sundialservices.com/products/chimneysweep

Re:TStringList objects


Nope, the strings are freed when their reference count goes to 0,  just not
the objects.    _________________________
Gary
http://www.delphiforfun.org
_________________________

Quote
"Jim Andrews" <j...@azdogs.com> wrote in message

news:39F4CCB7.FB5BEAB0@azdogs.com...
Quote
> Hello

> Does that mean this the code,
> var
>   j : integer;
>   SL : tStringList;
> begin
> SL := tstringlist.create(self);
> for j := 1 to 1000 do
> SL.items.add(inttostr(j));
> SL.clear;
> SL.free;
> SL := nil;
> end;

> leaves 1000 strings floating in memory without being "freed"?

> Sundial Services wrote:

> > The answer is emphatically -no- despite what the Delphi documentation
> > might inadvertantly imply.  None of the list-objects free any of the
> > objects attached to them.  (And if you think about it, in the general
> > case you probably would not want them to.)

> > This gives rise to procedures like this one:

> >         procedure DetonateExplosivesBeneath(var s: TStringList);
> >         var n: integer;
> >         begin
> >           if s = nil then exit;
> >           try
> >             for n := 0 to s.Count - 1 do s.objects[n].free;
> >           finally
> >             s.free;
> >             s := nil;   {my eternal habit to do this}
> >           end;
> >         end;

> > Notice this routine is written slightly more elaborately than it could
> > be.  But it is, except for the fanciful name, essentially what I use.

> > >guy bashan wrote:

> > > Hello,

> > > Does the method Delete for removing item from the string list takes
care of
> > > releasing the place of the Objetc in the list ??

> > ------------------------------------------------------------------
> > Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
> > mailto:i...@sundialservices.com  (PGP public key available.)
> > > Fast(!), automatic table-repair with two clicks of the mouse!
> > > ChimneySweep(R):  "Click click, it's fixed!" {tm}
> > > http://www.sundialservices.com/products/chimneysweep

Re:TStringList objects


In your example, you're not assigning any objects at all.  Clear will
reallocate exactly 0 bytes of memory (thereby, freeing the memory it used
for each item pointer before).  However, it will not  free the object that
each pointer was pointing to...as was said earlier.

After looking through Classes.pas...it seems to work like this:

First, TStringList is actually a list of pointers to TStringItems...defined
below:

  TStringItem = record
    FString: String;
    FObject: TObject;
  end;

TStringList.Delete moves all the pointers to TStringItems in the list up in
the list by 1...and decrements Count by 1.  Therefore, at this point,
Count<>Capacity.  There are still Capacity-Count pointers that aren't doing
anything but taking up memory.  The way to free the unused memory there is
to A) Use list.Capacity:=list.Count, or B) list.Clear (which sets the
Capacity to 0).  By settings the Capacity, you are reallocating a new memory
block and releasing the old one.  All this applies only to the pointers in
the list, and not the objects that may be assigned to each one.

As far as this last question:
Strings in the list work like all other strings.  What I mean by that is
that they are reference counted.  Once you remove the reference to them (the
pointer in the stringlist), their reference count should become 0 and the
memory for them will be freed automatically.

Someone correct me if I'm wrong.

Hope it helps,
Shane Bridges

Quote
"Jim Andrews" <j...@azdogs.com> wrote in message

news:39F4CCB7.FB5BEAB0@azdogs.com...
Quote
> Hello

> Does that mean this the code,
> var
>   j : integer;
>   SL : tStringList;
> begin
> SL := tstringlist.create(self);
> for j := 1 to 1000 do
> SL.items.add(inttostr(j));
> SL.clear;
> SL.free;
> SL := nil;
> end;

Re:TStringList objects


In article <39F4CCB7.FB5BE...@azdogs.com>,
  Jim Andrews <j...@azdogs.com> wrote:

Quote
> Hello

> Does that mean this the code,
> var
>   j : integer;
>   SL : tStringList;
> begin
> SL := tstringlist.create(self);
> for j := 1 to 1000 do
> SL.items.add(inttostr(j));
> SL.clear;
> SL.free;
> SL := nil;
> end;

> leaves 1000 strings floating in memory without being "freed"?

    You have to give an example that actually compiles
before anyone can answer this question. Seriously, there
are various _different_ ways you could fix the errors, and
the answer is different, depending on what you meant to say.

    First, it's SL := tstringlist.create, not what you wrote.
Now the confusion is at the line

SL.items.add(inttostr(j));

TStringlist does not have an items property. If you meant

SL.strings.add(inttostr(j));

or equivalently

SL.add(inttostr(j));

then no, there's no problem, the strings take care of
themselves.

    Otoh it happens sometimes that people want to
add strings in the Objects of a TStringlist. I know
I do it all the time. If you say

SL.AddObject('some string', inttostr(j));

that doesn't compile either. You _can_ add a string
directly to the Objects array with a typecast:

SL.AddObject('some string', TObject(inttostr(j)));

but that's a _very_ bad idea. I'm not certain whether
it orphans the strings or not - what I suspect is that
it doesn't actually work, although it appears to at
first (my suspicion is that when you make that typecast
the string manager loses track of the fact that the
stringlist has a reference to that string and feels
free to deallocate it. Strings take care of themselves
_if_ you treat them as actual strings, not when they're
cast to something else. If it does work it will probably
leak memory. You should not typecast strings to non-strings
unless you're certain you know what's what.)

    If you want to add some strings to the Objects
the thing to do is to create a class that just
acts as a wrapper around those strings:

type
  TStringWrapper = class
    protected
      FData: string;
    public
      property Data: string read FData write FData;
      constructor Create(AData: string);
  end;

constructor TStringWrapper.Create(AData: string);
begin
  inherited Create;
  Data:= AData;
end;

Now to add those strings to the Objects you say

SL.AddObject('some string', TStringWrapper.Create(inttostr(j)));

And you make certain to Free the objects when you Free
the list.

- Show quoted text -

Quote
> Sundial Services wrote:

> > The answer is emphatically -no- despite what the Delphi
documentation
> > might inadvertantly imply.  None of the list-objects free any of the
> > objects attached to them.  (And if you think about it, in the
general
> > case you probably would not want them to.)

> > This gives rise to procedures like this one:

> >         procedure DetonateExplosivesBeneath(var s: TStringList);
> >         var n: integer;
> >         begin
> >           if s = nil then exit;
> >           try
> >             for n := 0 to s.Count - 1 do s.objects[n].free;
> >           finally
> >             s.free;
> >             s := nil;   {my eternal habit to do this}
> >           end;
> >         end;

> > Notice this routine is written slightly more elaborately than it
could
> > be.  But it is, except for the fanciful name, essentially what I
use.

> > >guy bashan wrote:

> > > Hello,

> > > Does the method Delete for removing item from the string list
takes care of
> > > releasing the place of the Objetc in the list ??

> > ------------------------------------------------------------------
> > Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
> > mailto:i...@sundialservices.com  (PGP public key available.)
> > > Fast(!), automatic table-repair with two clicks of the mouse!
> > > ChimneySweep(R):  "Click click, it's fixed!" {tm}
> > > http://www.sundialservices.com/products/chimneysweep

--
Oh, dejanews lets you add a sig - that's useful...

Sent via Deja.com http://www.deja.com/
Before you buy.

Re:TStringList objects


David C. Ullrich <david_ullr...@my-deja.com> wrote in message
news:8t4idp$glm$1@nnrp1.deja.com...

Quote

> SL.AddObject('some string', TObject(inttostr(j)));

> but that's a _very_ bad idea. I'm not certain whether
> it orphans the strings or not - what I suspect is that
> it doesn't actually work, although it appears to at
> first (my suspicion is that when you make that typecast
> the string manager loses track of the fact that the
> stringlist has a reference to that string and feels
> free to deallocate it. Strings take care of themselves
> _if_ you treat them as actual strings, not when they're
> cast to something else. If it does work it will probably
> leak memory. You should not typecast strings to non-strings
> unless you're certain you know what's what.)

I agree that its a bad idea. AFAIK, however, you can do it and it does work.
Since the reference count is stored with the string IMO its much more likely
that the string space would not be released unless the strings were
explicitly set to ''.

Re:TStringList objects


"Bruce Roberts" <b...@bounceitattcanada.xnet> skrev i melding
news:tfoJ5.77799$YG5.56038@tor-nn1.netcom.ca...

Quote

> David C. Ullrich <david_ullr...@my-deja.com> wrote in message
> news:8t4idp$glm$1@nnrp1.deja.com...

> > SL.AddObject('some string', TObject(inttostr(j)));

> > but that's a _very_ bad idea. I'm not certain whether
> > it orphans the strings or not - what I suspect is that
> > it doesn't actually work, although it appears to at
> > first (my suspicion is that when you make that typecast
> > the string manager loses track of the fact that the
> > stringlist has a reference to that string and feels
> > free to deallocate it. Strings take care of themselves
> > _if_ you treat them as actual strings, not when they're
> > cast to something else. If it does work it will probably
> > leak memory. You should not typecast strings to non-strings
> > unless you're certain you know what's what.)

> I agree that its a bad idea. AFAIK, however, you can do it and it does
work.
> Since the reference count is stored with the string IMO its much more
likely
> that the string space would not be released unless the strings were
> explicitly set to ''.

I'm doing this excessively, allocating a record buffer concisting of a
block of of 4-byte integers, 1-byte booleans, 8-byte Doubles, etc.
....and 4-byte fields casted from pointer to string and back again.
Freeing up the allocated string just by setting String(Pointer^):=''.

The only trouble I've seen so far, is that errors done anywhere in my
apps have a tendency of ending up crashing some low-level
string-handling "magic". And it's really a pain in the ass, some
times...It should be mentioned that the programming style is quite
hazardious, with lots of raw typecasts.

--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:TStringList objects


In article <tfoJ5.77799$YG5.56...@tor-nn1.netcom.ca>,
  "Bruce Roberts" <b...@bounceitattcanada.xnet> wrote:

Quote

> David C. Ullrich <david_ullr...@my-deja.com> wrote in message
> news:8t4idp$glm$1@nnrp1.deja.com...

> > SL.AddObject('some string', TObject(inttostr(j)));

> > but that's a _very_ bad idea. I'm not certain whether
> > it orphans the strings or not - what I suspect is that
> > it doesn't actually work, although it appears to at
> > first (my suspicion is that when you make that typecast
> > the string manager loses track of the fact that the
> > stringlist has a reference to that string and feels
> > free to deallocate it. Strings take care of themselves
> > _if_ you treat them as actual strings, not when they're
> > cast to something else. If it does work it will probably
> > leak memory. You should not typecast strings to non-strings
> > unless you're certain you know what's what.)

> I agree that its a bad idea. AFAIK, however, you can do it and it does
work.
> Since the reference count is stored with the string IMO its much more
likely
> that the string space would not be released unless the strings were
> explicitly set to ''.

   You're being very brave here, taking the risk of becoming
a "target" (readers who wonder what that means should just never
mind.)

    You may well be right about what happens - that was actually
my first guess, don't recall why I changed it. If you're right that's
an instance of what I was getting at when I said strings take care
of themselves as long as you treat them as strings. The point to
these huge string things as I see it is you're not supposed to
have to worry about deallocating them. (Which may well be your point
as well.)

--
Oh, dejanews lets you add a sig - that's useful...

Sent via Deja.com http://www.deja.com/
Before you buy.

Re:TStringList objects


In article <ACrJ5.14233$W31.217...@news1.online.no>,
  "Bj?rge S?ther" <REMOVE_bsaether@THIS_online.no> wrote:

Quote
> "Bruce Roberts" <b...@bounceitattcanada.xnet> skrev i melding
> news:tfoJ5.77799$YG5.56038@tor-nn1.netcom.ca...

> > David C. Ullrich <david_ullr...@my-deja.com> wrote in message
> > news:8t4idp$glm$1@nnrp1.deja.com...

> > > SL.AddObject('some string', TObject(inttostr(j)));

> > > but that's a _very_ bad idea. I'm not certain whether
> > > it orphans the strings or not - what I suspect is that
> > > it doesn't actually work, although it appears to at
> > > first (my suspicion is that when you make that typecast
> > > the string manager loses track of the fact that the
> > > stringlist has a reference to that string and feels
> > > free to deallocate it. Strings take care of themselves
> > > _if_ you treat them as actual strings, not when they're
> > > cast to something else. If it does work it will probably
> > > leak memory. You should not typecast strings to non-strings
> > > unless you're certain you know what's what.)

> > I agree that its a bad idea. AFAIK, however, you can do it and it
does
> work.
> > Since the reference count is stored with the string IMO its much
more
> likely
> > that the string space would not be released unless the strings were
> > explicitly set to ''.

> I'm doing this excessively, allocating a record buffer concisting of a
> block of of 4-byte integers, 1-byte booleans, 8-byte Doubles, etc.
> ....and 4-byte fields casted from pointer to string and back again.
> Freeing up the allocated string just by setting String(Pointer^):=''.

    What do you gain by doing this instead of using fields of type
string and casting them to Pointer (or PChar) when you feel the need?
Then you should not have to worry about deallocating the space.
There must be some advantage to doing what you say you're doing
but I don't see what it is.

Quote
> The only trouble I've seen so far, is that errors done anywhere in my
> apps have a tendency of ending up crashing some low-level
> string-handling "magic".

    And there are disadvantages.

Quote
> And it's really a pain in the ass, some
> times...It should be mentioned that the programming style is quite
> hazardious, with lots of raw typecasts.

> --
> Bjoerge Saether
> Consultant / Developer
> Asker, Norway
> bsaether.removet...@online.no (remove the obvious)

--
Oh, dejanews lets you add a sig - that's useful...

Sent via Deja.com http://www.deja.com/
Before you buy.

Re:TStringList objects


"David C. Ullrich" <david_ullr...@my-deja.com> skrev i melding
news:8t6sgj$chr$1@nnrp1.deja.com...
Quote
> In article <ACrJ5.14233$W31.217...@news1.online.no>,
>   "Bj?rge S?ther" <REMOVE_bsaether@THIS_online.no> wrote:

> > I'm doing this excessively, allocating a record buffer concisting of
a
> > block of of 4-byte integers, 1-byte booleans, 8-byte Doubles, etc.
> > ....and 4-byte fields casted from pointer to string and back again.
> > Freeing up the allocated string just by setting

String(Pointer^):=''.

Quote

>     What do you gain by doing this instead of using fields of type
> string and casting them to Pointer (or PChar) when you feel the need?
> Then you should not have to worry about deallocating the space.
> There must be some advantage to doing what you say you're doing
> but I don't see what it is.

1. It's easy. No need for StrAlloc / StrDispose. Only a
String(Pointer^):=''; to dispose. One typecast instead of 2 in many
cases.
2. It's fast. Delphi strings are more efficient than PChars because of
reference counting and copy-when-changed functionality. OTOH, I didn't
check whether this is still the case after strings were thread-safe...

Quote
> > The only trouble I've seen so far, is that errors done anywhere in
my
> > apps have a tendency of ending up crashing some low-level
> > string-handling "magic".

>     And there are disadvantages.

I had this problem today in 2 different versions: 1) I was using
ReAllocMem without clearing the extended buffer, 2) I missed allocating
a buffer large enough. Both were hard to find, because ther error shows
a totally different place from where it was produced or where you would
expect to get an error. But that's a general problem when working with
dynamically allocated memory blocks.

--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:TStringList objects


David C. Ullrich <david_ullr...@my-deja.com> wrote in message
news:8t6s9u$cei$1@nnrp1.deja.com...

Quote

>    You're being very brave here, taking the risk of becoming
> a "target" (readers who wonder what that means should just never
> mind.)

;-)

Quote

>     You may well be right about what happens - that was actually
> my first guess, don't recall why I changed it. If you're right that's
> an instance of what I was getting at when I said strings take care
> of themselves as long as you treat them as strings. The point to
> these huge string things as I see it is you're not supposed to
> have to worry about deallocating them. (Which may well be your point
> as well.)

Yep, one shouldn't have to worry about de/allocation of long strings. But
when one uses them in the way that we've been discussing, one does have to
worry and, as I think we both agree, that's not such a good idea.

Re:TStringList objects


"Bruce Roberts" <b...@bounceitattcanada.xnet> skrev i melding
news:xKHJ5.78360$YG5.56879@tor-nn1.netcom.ca...

Quote

> David C. Ullrich <david_ullr...@my-deja.com> wrote in message
> news:8t6s9u$cei$1@nnrp1.deja.com...

> >    You're being very brave here, taking the risk of becoming
> > a "target" (readers who wonder what that means should just never
> > mind.)

> ;-)

> >     You may well be right about what happens - that was actually
> > my first guess, don't recall why I changed it. If you're right
that's
> > an instance of what I was getting at when I said strings take care
> > of themselves as long as you treat them as strings. The point to
> > these huge string things as I see it is you're not supposed to
> > have to worry about deallocating them. (Which may well be your point
> > as well.)

> Yep, one shouldn't have to worry about de/allocation of long strings.
But
> when one uses them in the way that we've been discussing, one does
have to
> worry and, as I think we both agree, that's not such a good idea.

Hi ! I did a recapitulation on how to do this:

procedure TForm1.ButtonAllocClick(Sender: TObject);
var
  i   : integer;
  PStr: Pointer;
begin
  For i:=0 to 50 do begin
// First, you need to nil' the pointer:
    PStr:=nil;
// And, it's important you don't store the string value in a string
variable:
    String(PStr):='Item #'+IntToStr(i);
    LB1.Items.AddObject('', TObject(PStr));
  end;
end;

procedure TForm1.LB1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
begin
  LB1.Canvas.FillRect(Rect);
  LB1.Canvas.TextOut(Rect.Left+2, Rect.Top+1,
String(LB1.Items.Objects[Index]));
end;

procedure TForm1.ButtonClearClick(Sender: TObject);
type
  PBuf = ^Pointer;
var
  i: integer;
  P: Pointer;
begin
  For i:=0 to 50 do begin
    P:=Pointer(LB1.Items.Objects[i]);
    String(P):='';
// Now, P = nil; - like magic !
  end;
  LB1.Items.Clear;
end;

...it may be a little easier syntactically with PChars (could do it with
2 lines on Alloc, I guess), but this wasn't *that* hard, was it ? And,
it's as safe as any other concept once you get the crucial 5 lines (3 on
alloc, 2 on dealloc) right.

--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:TStringList objects


On Tue, 24 Oct 2000 17:55:09 GMT, David C. Ullrich

Quote
<david_ullr...@my-deja.com> wrote:
>    If you want to add some strings to the Objects
>the thing to do is to create a class that just
>acts as a wrapper around those strings:

Thank you.
I further want to store a record of say three integers as the object.
Any idea how to do that, and of course how to access the values
please?
Thank you
Johan Smit
Go to page: [1] [2]

Other Threads