PDA

View Full Version : delete object on a list



slenkar
23-11-2010, 08:42 PM
if i want to remove an object from a list and free it from memory do i do this?


myobj=obby.create;
mylist.add(myobj);

for i:=0 to mylist.count-1 do
begin
if mylist[i].name='trev'
begin
mylist.delete(i); //removes object from list
mylist[i].free;//frees from memory
exit;
end;
end;


also, is there a command to remove all objects from a list AND free their memory?

code_glitch
23-11-2010, 08:46 PM
dont quite get when you want the for loop to stop and I think there might be a small error in the last line since you're treating it as an array of [mylist] and not as an object in a list... Slight difference. What data type are you using?

slenkar
23-11-2010, 08:50 PM
a custom type 'obby'

I can stop the loop by using exit at any time?

I altered the first post to reflect what i want to do

Brainer
23-11-2010, 08:59 PM
Your code looks correct to me. :) If you want to clear a list, use the Clear method.

Also, to make sure your object is freed after deletion, you can use the TObjectList class from Contnrs. Usage:


uses
Contnrs;

var
Objs: TObjectList = nil;
begin
Objs := TObjectList.Create(True);

Or if you use D2009/D2010/XE, check the Generics.Containers unit out. :)

slenkar
23-11-2010, 09:16 PM
so if i use objs.clear()
all objects on the list will be freed from memory as well as cleared off the list?

WILL
23-11-2010, 10:10 PM
Not sure if it's just the way you are entering your code into the code block or not, but do try to make good use of your white space. I'm not saying part everything everywhere, but those little spaces between the equals sign (=), nicely tabbing your code blocks and such really do help make your code easy for yourself and others to read.

Another thing that would help with clarity is when creating conditional statement is you use the ( and ) brackets to encase your conditions. It makes it easier to spot your conditional IF statements and if you should require a complex set of conditions it would make it so much easier to understand and write. And lets not forget to add the "then", though if you program in both C-style and Pascal-style languages you'll make this mistake often after coming back to Pascal after a time. ;)

Besides the clarity of the code... think of a list as an array of records. Except, it's not records, it's objects so you have to free each one unless there is a method or function that will do this for you, such as TObjectList.Clear();

You can make such a procedure or method yourself if you prefer just be sure to keep proper track of what objects are created/allocated. If you don't keep track of what is created and what needs to be freed in your program, then this is where memory leaks happen. And those aren't nice if you plan on running your program for long periods of time, or at any time really depending on the size of the leak. Best practice is to prevent them from occurring at all.

slenkar
23-11-2010, 11:14 PM
thanks for the help:

I created a little example program


program listexample;

{$mode objfpc}{$H+}

uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, Contnrs ,crt
{ you can add units after this };

type
obby=class(Tobject)
name:string;
end;
var
o:obby;
obby_list:Tobjectlist;
iter1:integer;
iter2:integer;

{$IFDEF WINDOWS}{$R listexample.rc}{$ENDIF}

begin
obby_list:=Tobjectlist.create(true);
REPEAT

for iter1:=0 to 10 do
begin
for iter2:=0 to 10 do
begin
obby_list.add(obby.create);
end;
obby_list.clear();
end;


UNTIL keypressed;

end.


sorry for any lack of formatting
I went into windows taskmanager and the program stayed the same size so no memory leaks so far

I tried learning C++ and it was very difficult,
I was using a vector and my program had a memory leak which I couldnt get rid of.
looks like it will be a lot easier to create DS games with pascal.

slenkar
23-11-2010, 11:49 PM
AAARRRRGGGHHHHH

Ive been scouring the internet for an example of how to remove an object from a Tobjectlist with no luck



program listexample;

{$mode objfpc}{$H+}

uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, Contnrs ,crt
{ you can add units after this };

type
obby=class(Tobject)
name:string;
end;
var
o:obby;
obby_list:Tobjectlist;
iter1:integer;
iter2:integer;
iter3:integer;
obj:Tobject;
{$IFDEF WINDOWS}{$R listexample.rc}{$ENDIF}

begin
obby_list:=Tobjectlist.create(true);
REPEAT

for iter1:=0 to 10 do
begin
for iter2:=0 to 10 do
begin
obby_list.add(obby.create);
end;
end;

for iter3:=0 to obby_list.count-1 do
begin
obj:=obby_list.items[iter3];
obby_list.remove(obj);
end;


UNTIL keypressed;

end.


this example crashes with exception 'unknown'

Srki_82
24-11-2010, 07:55 AM
Change "remove" code to:

for iter3:=obby_list.count-1 downto 0 do
begin
obj:=obby_list.items[iter3];
obby_list.remove(obj);
end;

DarkBow
24-11-2010, 11:58 AM
AAARRRRGGGHHHHH

Ive been scouring the internet for an example of how to remove an object from a Tobjectlist with no luck




for iter3:=0 to obby_list.count-1 do
begin
obj:=obby_list.items[iter3];
obby_list.remove(obj);
end;



this example crashes with exception 'unknown'

Just to clarify it a bit, that code snippet will not work, but Srki_82's code will. The problem is that both Remove and Delete methods remove the the object from the list and move all objects that were behind it in the list 1 position up in the list, i.e, when you remove the first object on position 0, the object on position 1 moves to position 0, the object on position 2 to position 1, etc.

Regarding the memory, as long the property OwnsObjects is true Remove will free the object. Not sure if Delete will.

Dan
24-11-2010, 06:17 PM
short and simple:


obby_list.Clear;

this will free all the items and clear the list, assuming the class of obby_list is TObjectList.

slenkar
24-11-2010, 08:53 PM
Just to clarify it a bit, that code snippet will not work, but Srki_82's code will. The problem is that both Remove and Delete methods remove the the object from the list and move all objects that were behind it in the list 1 position up in the list, i.e, when you remove the first object on position 0, the object on position 1 moves to position 0, the object on position 2 to position 1, etc.

Regarding the memory, as long the property OwnsObjects is true Remove will free the object. Not sure if Delete will.

thanks both of you, i couldnt find any example of how to remove a single object from a Tobjectlist anywhere :)

User137
25-11-2010, 01:15 AM
It's the same principle with any array. "For" works different in C than pascal. For example:

// This loop would print all numbers 1 to 10... They become like constants for the loop at beginning
num:=10;
for i:=1 to num do begin
num:=1;
writeln(inttostr(i));
end;

// Same in C would just print 1
num=10;
for (int i=1; i<=num; i++) {
num=1;
printf("%d",i);
}

So you have to restrict what you are deleting from the array or list. Simplest was like mentioned from end to start

for i:=0 to list.count-1 do
if MarkedForDeletion(list[i]) then list.Delete(i);

But ofc you can do it other ways like:

i:=0;
while (i<list.count) do begin
if MarkedForDeletion(list[i]) then list.Delete(i)
else inc(i);
end;

slenkar
25-11-2010, 04:15 PM
ohhh so the listcount isnt updated every loop in a FOR loop
but in a WHILE loop it IS updated?

I take it that is a compiler optimisation thingy