?
Solved

getting an object pointed by an item within a Tlist  in delphi6

Posted on 2003-03-06
17
Medium Priority
?
234 Views
Last Modified: 2010-04-04
It is easy to create bug with pointer so I would like to check the following (I know Tobjectlist  is more handy but I try to findout a bug in a code written with TLIST) :

Assume I have a class
TmyObject = class(TObject)
...whatever

PmyObject = ^TmyObject;

If I have a procedure with
var myobject,myobject2:tmyobject;
Flist:Tlist;
begin
Flist:=Tlist.create;
myobject:=Tmyobject.create;
Flist.add(myobject)// suspicious line 1
.....
end;

Is the suspicious line above correct or could it cause a bug ? As Myobject is essentially a pointer It should be ok and it is accepted by the compiler but there might be something wrong with this coding.

Some more : assume I want to access to the object pointed by Flist.items[0] consider the two following possibilities :

myobject2:=PMyobject(Flist.items[0])^;
myobject2:=Tmyobject(Flist.items[0]);

Are they both correct ?

Thanks in Advance.





0
Comment
Question by:Soko
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 4
  • +2
17 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 8078896
if you add it in this way

Flist.add(myobject);

then you get it in this way

myobject:=Tmyobject(Flist.items[IndexYouHaveHere]);

PmyObject is not needed

meikl ;-)
0
 

Author Comment

by:Soko
ID: 8078992
OK That was my feeling too but I wanted to check. I will wait a little if you don't mind and If I don't get any other comment telling me that something could be buggy there I will give the points (-:

By the way do you agree that the following is buggy ? :
myobject:=Flist.items[IndexYouHaveHere];
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8079084
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 27

Expert Comment

by:kretzschmar
ID: 8079378
myobject:=Flist.items[IndexYouHaveHere];

you need a typecast here,
because pointer and tobject are not of same type,
even a tobject is a pointer (the compiler may not compile)

use
myobject:=Tmyobject(Flist.items[IndexYouHaveHere]);
instead

meikl ;-)
0
 
LVL 2

Expert Comment

by:j42
ID: 8079856
Hi,

Just to chip in my lot:
From a TList you will get what you throw in:

A)
myList.Add(TMyObj.Create);
...
myObj := TMyObj(myList.Items[i]);

B)
myList.Add(@TMyObj.Create)
...
myObj := PMyObj(myList.Items[i])^;



Regards
0
 

Author Comment

by:Soko
ID: 8081767
J42 Your answer ring a bell :Tlist is a pointer list so what is the exact difference between myList.Add(TMyObj.Create and myList.Add(@TMyObj.Create) ?
myList.Items[i] is a pointer in both case .

May be in case A myList.Items[i] point to the object and in case B myList.Items[i] point to a pointer which point to the object ? I'm not sure
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 8082003
with @.. you store the adress of the pointer to the object

->pointer^.object

without you have a object

->object

keep in mind the tobject is already a pointer,
but strongly typed, whereas a pointer is "typeless",
thats why you need a typecast


btw
if stored in this way
myList.Add(@TMyObj.Create)

this
myObj := PMyObj(myList.Items[i])^;

is the same as this
myObj := TMyObj(myList.Items[i]^);

you see, also here is PMyObj not really needed

meikl ;-)





0
 
LVL 3

Accepted Solution

by:
sfock earned 200 total points
ID: 8082317
just trying to make it a bit more clear:

1. the content of a variable of the type TAnyObject is a Reference
2. A Reference is _not_ a pointer (even if it is pretty similar in sense)
3. the operator @ returns the pointer of the variable passed after the operater so that : @myObject returns the address of the reference of the instance of TMyObject
4. the type of an object reference and a pointer are both 32bit long values wich makes it possible to cast them to each other for storing reasons.
5. of that follows that myobject2:=PMyobject(Flist.items[0])^;
is a bug because you treat the reference as a pointer and try to deref it and assign this to a ObjectReference variable
If you'd add(@myObject); it would be okay

i hope that helps to clear the thing up
0
 

Author Comment

by:Soko
ID: 8082908
I See so thank you sfock for this explanations and also thank you  kretzschmar. Now If I have understood things well the following should be bug (not  obvious at first glance)

var Flist:Tlist;
Myobject1:Tmyobject;

procedure Duplicate;
var Myobject2:Tmyobject;
begin
Myobject2:=Pmyobject(Flist.items[0])^;
Flist.add(@myobject2);
end;

begin
Flist.create;
Flist.add(Myobject.create);
Duplicate;
Myobject1:=Pmyobject(Flist.items[1])^;
....
end;

I think it is a bug because once the procedure Duplicate end, myobject2 reference disappear and therefore Flist.items[1]) is pointing to an irrelevant address. Am I correct here ?
0
 
LVL 3

Expert Comment

by:sfock
ID: 8083054
yes right.

To correct the code do the following:

var Flist:Tlist;
Myobject1:Tmyobject;

procedure Duplicate;
begin
Flist.add(Flist.items[0]);
end;

begin
Flist.create;
Flist.add(Myobject.create);
Duplicate;
Myobject1:=Tmyobject(Flist.items[1]);
....
end;

Just try to imagine it like this : TList stores pointers, pointers are 32-BitValues. Object references are 32-bit values too so you can Hard cast them without changing the representation. if you call "Flist.add(Myobject.create);" delphi makes an implicit cast for you. when you retrieve the 32-bit value back you have to cast it back to the type it actually is.
But dont forget, you do not duplicate a object instance here you are only duplicating a object reference
0
 
LVL 2

Expert Comment

by:j42
ID: 8083441
Hi sfock,

> 5. of that follows that myobject2:=PMyobject(Flist.items[0])^;
> is a bug

Will you really call it a bug? I suppose it will compile and run. Maybe it is bad style unless you have a good reason to do it that way...

Best of luck
J
0
 
LVL 3

Expert Comment

by:sfock
ID: 8083564
Hi j42

well yes it will compile but not run, if you have added the object with list.add(myObject);.
In this sense i was unprecise because if you add list.add(@myObject); will work fine, unless the "myObject" variable ist still valid when trying to get it.

you might veryfy that

procedure TForm1.Button1Click(Sender: TObject);
type
  PObj = ^TObject;
var
  obj : TObject;
  lst : TList;
begin
  lst := TList.create;
  obj := TObject.create;
  lst.Add(obj);
  //lst.Add(@obj);
  showMessage(IntToStr(PObj( lst.Items[0])^.InstanceSize));
  obj.free;
  lst.free;
end;

will cause an AV. If you comment lst.Add(@obj); in and lst.Add(obj); out it will of corse run, but don't try the same over the edge of the current stack frame ;-)
0
 

Author Comment

by:Soko
ID: 8086970
Ok sfock Thank you very much.Things are clear now. Both  kretzschmar, j42 and yourself have been very helpfull but I Think that your answer was more complete and make me understand what is correct and what is not and also the reason behind it. So I Think I should give the points to you if kretzschmar and j42 don't mind ?
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 8087003
i agree to give the points to sfock for best explaination

meikl ;-)
0
 
LVL 2

Expert Comment

by:j42
ID: 8087109
Me too!

Regards
J
0
 
LVL 2

Expert Comment

by:j42
ID: 8087126
kretzschmar,

> myObj := TMyObj(myList.Items[i]^);
I know this will work but I do not know why! It takes the content of a typeless pointer. What is that? Compiler magic?
0
 
LVL 3

Expert Comment

by:sfock
ID: 8090281
thanks for the flowers guys ;-)

j42
myObj := TMyObj(myList.Items[i]^);
is no compiler magic and it works if you added the following way:
myList.Add(@myObject);

so remember the add command add's a pointer to a reference

myList.Items[i] returns the pointer with dereferencing it you get the reference itself where windows finds the referenece and with the hard cast TMyObj() you simply take any doubt from the compiler that you really want to treat the next 4 bytes at this memory position as a Object reference of the type TMyObj and assign it to the local variable.

0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses
Course of the Month13 days, 17 hours left to enroll

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question