Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2003-05

ReAlloc Question

15 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

James Mills

Hi,

Can any problems with stringsclass.pas ?
Reason I ask is that, yes my fairly large program works that uses dynamic memory allocation, however it has memory leaks galore! :( stringsclass.pas is a dynamic string class I created which I take pride in, but I'm not convinced I wrote the: procedure del(index: Integer); correctly...
Could someone have a look and comment on that please ? It will aid greatly in my efforts to debug my memory leaks...

cheers
James

Michael Van Canneyt
to James Mills
James Mills wrote 10 lines
Hi, Can any problems with stringsclass.pas ? Reason I ask is that, yes my fairly large program works that uses dynamic memory allocation, however it has memory leaks galore! :( stringsclass.pas is a dynamic string class I created which I take pride in, but I'm not convinced I wrote the: procedure del(index: Integer); correctly... Could someone have a look and comment on that please ? It will aid greatly in my efforts to debug my memory leaks...

With all due respect, but this is not exactly the most efficient code ever. Did you have a look at the standard TStringList class ? It works very well, and does all you do.

Also, Class destructors MUST be called 'Destroy', not 'done'.

Your method of calling init/done is also not quite correct, you're not supposed to call the destructor unless you actually want to free your class.

If you want to stick to your class, try replacing your code with this=

procedure TStrings.del(index: Integer);
var
 I : Integer;
begin
 For I:=index to nstrings-1 do
   Strings[i]:=Strings[i+1];
 Dec(nstrings);
 ReallocMem(strings,sizeof(Shortstring)*nstrings);
end;

Using this I get no memory leaks.

Michael.

James Mills
to Michael Van Canneyt
Michael Van Canneyt wrote 18 lines
On Fri, 16 May 2003, James Mills wrote: > Hi, > > Can any problems with stringsclass.pas ? > Reason I ask is that, yes my fairly large program works that uses > dynamic memory allocation, however it has memory leaks galore! :( > stringsclass.pas is a dynamic string class I created which I take pride > in, but I'm not convinced I wrote the: procedure del(index: Integer); > correctly... > Could someone have a look and comment on that please ? It will aid > greatly in my efforts to debug my memory leaks... With all due respect, but this is not exactly the most efficient code ever. Did you have a look at the standard TStringList class ? It works very well, and does all you do.

Yeah I found out there was TStringList after I wrote it. And I'll agree with you, it's not the best code. However other classes that dynamically allocate objects in memory use similar code to that of stringsclass.pas so I need to get this right :)

Also, Class destructors MUST be called 'Destroy', not 'done'.

Okay.

Show quoted text 17 lines
Your method of calling init/done is also not quite correct, you're not supposed to call the destructor unless you actually want to free your class. If you want to stick to your class, try replacing your code with this= procedure TStrings.del(index: Integer); var I : Integer; begin For I:=index to nstrings-1 do Strings[i]:=Strings[i+1]; Dec(nstrings); ReallocMem(strings,sizeof(Shortstring)*nstrings); end;

Would this same technique work for a general dynamic array of objects ?

Using this I get no memory leaks.

I get none with my version either (don't know why) ...

James

Show quoted text 7 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
James Mills
to Michael Van Canneyt: It should, unless you use memory pointers that point to specific memory locations in the…
Michael Van Canneyt wrote 56 lines
On Fri, 16 May 2003, James Mills wrote: > On Fri, May 16, 2003 at 01:41:35PM +0200, Michael Van Canneyt wrote: > > > > > > On Fri, 16 May 2003, James Mills wrote: > > > > > Hi, > > > > > > Can any problems with stringsclass.pas ? > > > Reason I ask is that, yes my fairly large program works that uses > > > dynamic memory allocation, however it has memory leaks galore! :( > > > stringsclass.pas is a dynamic string class I created which I take pride > > > in, but I'm not convinced I wrote the: procedure del(index: Integer); > > > correctly... > > > Could someone have a look and comment on that please ? It will aid > > > greatly in my efforts to debug my memory leaks... > > > > With all due respect, but this is not exactly the most efficient code ever. > > Did you have a look at the standard TStringList class ? It works very well, > > and does all you do. > > Yeah I found out there was TStringList after I wrote it. And I'll agree > with you, it's not the best code. However other classes that dynamically > allocate objects in memory use similar code to that of stringsclass.pas > so I need to get this right :) > > > > > > > Also, Class destructors MUST be called 'Destroy', not 'done'. > Okay. > > > > > Your method of calling init/done is also not quite correct, you're not > > supposed to call the destructor unless you actually want to free your > > class. > > > > If you want to stick to your class, try replacing your code with this= > > > > procedure TStrings.del(index: Integer); > > var > > I : Integer; > > > > begin > > For I:=index to nstrings-1 do > > Strings[i]:=Strings[i+1]; > > Dec(nstrings); > > ReallocMem(strings,sizeof(Shortstring)*nstrings); > > end; > > Would this same technique work for a general dynamic array of objects ? It should, unless you use memory pointers that point to specific memory locations in the array.

I'll show you... Catch, datanicks.pas and nickclass.pas ... This is why I need to understand and fix this, it's not just a simple TStringList that I want to use :)

thanks for your help ...

cheers
James

Show quoted text 7 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Michael Van Canneyt
to James Mills: Yeah I found out there was TStringList after I wrote it. And I'll agree with you, it's…
James Mills wrote 49 lines
On Fri, May 16, 2003 at 01:41:35PM +0200, Michael Van Canneyt wrote: > > > On Fri, 16 May 2003, James Mills wrote: > > > Hi, > > > > Can any problems with stringsclass.pas ? > > Reason I ask is that, yes my fairly large program works that uses > > dynamic memory allocation, however it has memory leaks galore! :( > > stringsclass.pas is a dynamic string class I created which I take pride > > in, but I'm not convinced I wrote the: procedure del(index: Integer); > > correctly... > > Could someone have a look and comment on that please ? It will aid > > greatly in my efforts to debug my memory leaks... > > With all due respect, but this is not exactly the most efficient code ever. > Did you have a look at the standard TStringList class ? It works very well, > and does all you do. Yeah I found out there was TStringList after I wrote it. And I'll agree with you, it's not the best code. However other classes that dynamically allocate objects in memory use similar code to that of stringsclass.pas so I need to get this right :) > > > Also, Class destructors MUST be called 'Destroy', not 'done'. Okay. > > Your method of calling init/done is also not quite correct, you're not > supposed to call the destructor unless you actually want to free your > class. > > If you want to stick to your class, try replacing your code with this= > > procedure TStrings.del(index: Integer); > var > I : Integer; > > begin > For I:=index to nstrings-1 do > Strings[i]:=Strings[i+1]; > Dec(nstrings); > ReallocMem(strings,sizeof(Shortstring)*nstrings); > end; Would this same technique work for a general dynamic array of objects ?

It should, unless you use memory pointers that point to specific memory locations in the array.

Michael.

James Mills
to James Mills: I'll show you... Catch, datanicks.pas and nickclass.pas ... This is why I need to…
James Mills wrote 61 lines
On Fri, May 16, 2003 at 02:11:24PM +0200, Michael Van Canneyt wrote: > > > On Fri, 16 May 2003, James Mills wrote: > > > On Fri, May 16, 2003 at 01:41:35PM +0200, Michael Van Canneyt wrote: > > > > > > > > > On Fri, 16 May 2003, James Mills wrote: > > > > > > > Hi, > > > > > > > > Can any problems with stringsclass.pas ? > > > > Reason I ask is that, yes my fairly large program works that uses > > > > dynamic memory allocation, however it has memory leaks galore! :( > > > > stringsclass.pas is a dynamic string class I created which I take pride > > > > in, but I'm not convinced I wrote the: procedure del(index: Integer); > > > > correctly... > > > > Could someone have a look and comment on that please ? It will aid > > > > greatly in my efforts to debug my memory leaks... > > > > > > With all due respect, but this is not exactly the most efficient code ever. > > > Did you have a look at the standard TStringList class ? It works very well, > > > and does all you do. > > > > Yeah I found out there was TStringList after I wrote it. And I'll agree > > with you, it's not the best code. However other classes that dynamically > > allocate objects in memory use similar code to that of stringsclass.pas > > so I need to get this right :) > > > > > > > > > > > Also, Class destructors MUST be called 'Destroy', not 'done'. > > Okay. > > > > > > > > Your method of calling init/done is also not quite correct, you're not > > > supposed to call the destructor unless you actually want to free your > > > class. > > > > > > If you want to stick to your class, try replacing your code with this= > > > > > > procedure TStrings.del(index: Integer); > > > var > > > I : Integer; > > > > > > begin > > > For I:=index to nstrings-1 do > > > Strings[i]:=Strings[i+1]; > > > Dec(nstrings); > > > ReallocMem(strings,sizeof(Shortstring)*nstrings); > > > end; > > > > Would this same technique work for a general dynamic array of objects ? > > It should, unless you use memory pointers that point to specific memory > locations in the array. I'll show you... Catch, datanicks.pas and nickclass.pas ... This is why I need to understand and fix this, it's not just a simple TStringList that I want to use :)

Forgot to attach em :(

cheers
James

Show quoted text 17 lines
thanks for your help ... cheers James > > Michael. > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
James Mills
to Michael Van Canneyt: It should work with this class too. Michael.
Michael Van Canneyt wrote 8 lines
> > I'll show you... Catch, datanicks.pas and nickclass.pas ... > > This is why I need to understand and fix this, it's not just a simple > > TStringList that I want to use :) > > Forgot to attach em :( It should work with this class too.

Okay, thanks.

btw ... Is this how you write classess properly ? (destroy destructor as you said ...)

type
   TTokenizer = class(TObject)
      constructor init(tmpStr: String);
      constructor init(tmpStr: String; tmpDelim: Char);
      destructor destroy; override;

.
.
.

destructor TTokenizer.destroy;
begin
   inherited destroy;
end;
Show quoted text 7 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Unknown author

James,

didn't I send you a revised version of this ages ago... even if you dumped the whole of it I would have pointed out why not to use Init and Done over Create and Destroy. I'll tell you one good reason why you may have memory leaks... 'done' will never get called if you 'free' an instance of TStrings. That alone will cause a memory leak.

You did see TList too, right? TStringList and TList will do everything you want, and TObjectList is another good one (if fpc has it implemented.) For 1.1 also look out for TInterfaceList (one of my favourites in Delphi) and there's also the heavy handed but usefull TThreadList in multithreaded environments ;-)

In fact, looking at your code, your biggest problem is that you missed how the destructor works in Object Pascal. TObject has a virtual destructor called 'Destroy' that gets called when you call 'Free'. Calling the destructor directly is simply wrong. If you are using Turbo Pascal mode, you should be calling 'dispose( instance, destructor );' and in Object Pascal (Delphi like) mode it has to be 'instance.free' which will indirectly call the destructor. If you name your destructor something random and call it directly, it will leak memory like a sieve.

Also it would be worthwhile take a look how inheritence works. Look, for example, at the definition of TObject. The destructor is defined as 'destructor Destroy; virtual;'. The 'virtual' is the clue here. You must 'override' this method to get things to work propperly!! Your destructor needs to call 'inherited destructor' to have any chance at not leaking memory.

destructor TStrings.Destroy;
begin
  //whatever deallocation
  inherited; //also valid : 'inherited Destroy;'
  //like 'super' in java
end;

Naming your constructor as Init, whilst not technically incorrect, breaks naming conventions and will cause you endless problems if you should ever wish to derrive your class from somewhere else other than TObject. So, once interfaces come into play in 1.1, you would want to descend from TInterfacedObject, and not calling the inherited constructor could be a real problem. Another classic problem is TThread. Try creating a TThread descendent and overriding the constructor but not calling the inherited version. The thread never starts ;-) Got caught by that one a few times.

Matt

---------------------------------------------
This message was sent using Mistral WebMail.
http://www.mistral.co.uk/

James Mills
to Unknown author
Show quoted text 21 lines
James, didn't I send you a revised version of this ages ago... even if you dumped the whole of it I would have pointed out why not to use Init and Done over Create and Destroy. I'll tell you one good reason why you may have memory leaks... 'done' will never get called if you 'free' an instance of TStrings. That alone will cause a memory leak. You did see TList too, right? TStringList and TList will do everything you want, and TObjectList is another good one (if fpc has it implemented.) For 1.1 also look out for TInterfaceList (one of my favourites in Delphi) and there's also the heavy handed but usefull TThreadList in multithreaded environments ;-) In fact, looking at your code, your biggest problem is that you missed how the destructor works in Object Pascal. TObject has a virtual destructor called 'Destroy' that gets called when you call 'Free'. Calling the destructor directly is simply wrong. If you are using Turbo Pascal mode, you should be calling 'dispose( instance, destructor );' and in Object Pascal (Delphi like) mode it has to be 'instance.free' which will indirectly call the destructor. If you name your destructor something random and call it directly, it will leak memory like a sieve.

Okay, I didn't know this. Thanks. Sorry if you've tried helping me before, too much uni work I guess and it was a long time ago...

Show quoted text 25 lines
Also it would be worthwhile take a look how inheritence works. Look, for example, at the definition of TObject. The destructor is defined as 'destructor Destroy; virtual;'. The 'virtual' is the clue here. You must 'override' this method to get things to work propperly!! Your destructor needs to call 'inherited destructor' to have any chance at not leaking memory. destructor TStrings.Destroy; begin //whatever deallocation inherited; //also valid : 'inherited Destroy;' //like 'super' in java end; Naming your constructor as Init, whilst not technically incorrect, breaks naming conventions and will cause you endless problems if you should ever wish to derrive your class from somewhere else other than TObject. So, once interfaces come into play in 1.1, you would want to descend from TInterfacedObject, and not calling the inherited constructor could be a real problem. Another classic problem is TThread. Try creating a TThread descendent and overriding the constructor but not calling the inherited version. The thread never starts ;-) Got caught by that one a few times.

Thanks Matt :)
Be a lot of re-writing...

cheers
James

Show quoted text 12 lines
Matt --------------------------------------------- This message was sent using Mistral WebMail. http://www.mistral.co.uk/ _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Michael Van Canneyt
to Unknown author: didn't I send you a revised version of this ages ago... even if you dumped the whole of…
Show quoted text 10 lines
James, didn't I send you a revised version of this ages ago... even if you dumped the whole of it I would have pointed out why not to use Init and Done over Create and Destroy. I'll tell you one good reason why you may have memory leaks... 'done' will never get called if you 'free' an instance of TStrings. That alone will cause a memory leak. You did see TList too, right? TStringList and TList will do everything you want, and TObjectList is another good one (if fpc has it implemented.)

It is implemented.

Michael.

Michael Van Canneyt
to James Mills: Okay, thanks. btw ... Is this how you write classess properly ? (destroy destructor as…
James Mills wrote 29 lines
On Fri, May 16, 2003 at 03:05:30PM +0200, Michael Van Canneyt wrote: > > > > I'll show you... Catch, datanicks.pas and nickclass.pas ... > > > This is why I need to understand and fix this, it's not just a simple > > > TStringList that I want to use :) > > > > Forgot to attach em :( > > It should work with this class too. Okay, thanks. btw ... Is this how you write classess properly ? (destroy destructor as you said ...) type TTokenizer = class(TObject) constructor init(tmpStr: String); constructor init(tmpStr: String; tmpDelim: Char); destructor destroy; override; . . . destructor TTokenizer.destroy; begin inherited destroy; end;

This is OK. It's also customary to call the constructor 'Create'. It reflects more what is happening, namely that *new* memory is allocated. 'Init' reflects more that *existing* memory is initialized. (which is more an old TP construct)

Michael.

James Mills
to Michael Van Canneyt
Michael Van Canneyt wrote 38 lines
On Fri, 16 May 2003, James Mills wrote: > On Fri, May 16, 2003 at 03:05:30PM +0200, Michael Van Canneyt wrote: > > > > > > I'll show you... Catch, datanicks.pas and nickclass.pas ... > > > > This is why I need to understand and fix this, it's not just a simple > > > > TStringList that I want to use :) > > > > > > Forgot to attach em :( > > > > It should work with this class too. > > Okay, thanks. > > btw ... Is this how you write classess properly ? (destroy destructor as > you said ...) > > type > TTokenizer = class(TObject) > constructor init(tmpStr: String); > constructor init(tmpStr: String; tmpDelim: Char); > destructor destroy; override; > > . > . > . > > destructor TTokenizer.destroy; > begin > inherited destroy; > end; This is OK. It's also customary to call the constructor 'Create'. It reflects more what is happening, namely that *new* memory is allocated. 'Init' reflects more that *existing* memory is initialized. (which is more an old TP construct)

Okay. Thank you :)

James

Show quoted text 7 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
paradice
to Michael Van Canneyt: With all due respect, but this is not exactly the most efficient code ever. Did you have…

Hi everyone -

is there any way to call a virtual method of a class from within an assembler block/function/method?

I checked out FPC's generated-assembler source but it uses a constant-offset, e.g.:

movl (%esi),%edi
call *92(%edi)

the "*92" is the offset for that particular method in the classes' VMT, but is there any way I can obtain this number myself? (is it a named constant anywhere?? I only need it at compile-time) Calling the method by name works for that class but doesn't recognise "override" methods in descendents....

Thanks in advance...

Peter Vreman
to paradice
you wrote 17 lines
Hi everyone - is there any way to call a virtual method of a class from within an assembler block/function/method? I checked out FPC's generated-assembler source but it uses a constant-offset, e.g.: movl (%esi),%edi call *92(%edi) the "*92" is the offset for that particular method in the classes' VMT, but is there any way I can obtain this number myself? (is it a named constant anywhere?? I only need it at compile-time) Calling the method by name works for that class but doesn't recognise "override" methods in descendents.... Thanks in advance...

There is no way to retrieve this information, you need to calculate the offset yourself. Also note that the calling of methods will be little different between 1.1 and 1.0.x and it is therefor not recommended to call methods from assembler code. You can make a pascal wrapper arround the method

Peter