Difference between address and pointer

Say I have the following:

TCachedData = class(TObject)
  LatticeAddress : ^TLattice;
  constructor create();
end;

TCachedDataArray = class(TObject)
  caches : array of TCachedData;
  constructor create(size : Integer);

constructor TCachedData.create();
begin
  inherited;
  self.LatticeAddress := nil;
end;

constructor TCachedDataArray.create(size : Integer);
var
  Teller : Integer;
begin
  setlength(caches, size+1);
  for Teller := 0 to size do
  begin
    self.caches[Teller] := TCachedData.create;
  end;
end;

LatticeCache := TCachedDataArray.create(10);

And I use
Lattice := TLattice.create(.....)
LatticeCache.caches[current_ID].LatticeAddress := @Lattice;

What would be the difference if I was using:

TCachedData = class(TObject)
  LatticeAddress : TLattice;
  constructor create();
end;

 and

LatticeCache.caches[current_ID].LatticeAddress := Lattice;

instead?

Because I keep getting some errors when I try to do

LatticeCache.caches[current_ID].LatticeAddress.Free();

later on.

When I execute the following:

LatticeCache.caches[current_ID].LatticeAddress := Lattice;
LatticeCache.caches[current_ID].LatticeAddress.Free();

it works fine, but when I try to free a particular array element
(LatticeCache.caches[specific_ID_later_on].LatticeAddress.Free(); I get some errors. (this always happens the 2nd time I try to free any particular element, the first one works fine).

This could be due to some error in the code in the 'Lattice' part, but I just want to be sure I'm not making any mistakes here.
Help much appreciated!





reynaerdeAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
Slick812Connect With a Mentor Commented:
LatticeCache.caches[Teller].LatticeAddress^ := Lattice;
the above seems Incorrect to me, maybe it should be -
 LatticeCache.caches[Teller].LatticeAddress^ := TLattice.Create( );

this is a short comment, since the whole "Pointer"  and  "TObject" and Delphi memory workings are NOT simple and straight-forward (as you seem to have gathered by now. . . All variable size "variables" like a String and some TObject are different than fixed size variables like an Integer, TPoint, or TRect, Delphi handles the memory assignments for all TObjects and Strings, when you call

StrL1 := TStringList.Create;

the memory for a StringList "Object" is allocated and the memory positions for constansts, functions and variables are placed in the new string list TObject, , so I guess my view is that the StrL1 is a Pointer to a Pointer after you call the Create. . .

so you call -

new(LatticeCache.caches[Teller].LatticeAddress);

and this will get memory for the other pointer, there is already a "Pointer" memory (4 bytes) assigned for the "LatticeAddress"
if you do not call new( ) then there is NO memory allocated for the Object pointer

you will need to Dereference the LatticeAddress when you use it with create, Because it is a memory address (pointer) , , and the create should return the second mem address for the "Object"

LatticeCache.caches[Teller].LatticeAddress^ :=  TLattice.Create;

but there is more to the TObject, than just the other pointer

and as I see it

LatticeAddress : ^TLattice;

and

Lattice : TLattice;

are NOT the same, although with Delphi you can use the LatticeAddress as a TLattice in many cases (but not all), I would only use the ^TLattice if there was some code that FORCED me to use a Pointer type, other wize I would use the standard way with a TLattice, because you can most always use  @Lattice1  if you just got to have a pointer
0
 
vadim_tiCommented:
see, first of all there is no differrence between

TCachedData = class(TObject)
  LatticeAddress : ^TLattice;
  constructor create();
end;

and

TCachedData = class(TObject)
  Lattice : TLattice;
  constructor create();
end;

in any case Lattice will save pointer to TLattice object

now if Lattice is only member of TCachedData, may be you can use something
like this

TCachedData = class(TObject)
  constructor create();
end;

TLattice = class(TCachedData)
end;

TSomethingElse = class(TCachedData)
end;

now you can use
  LatticeArray[i] := TLattice.Create(nil);

i also do not think you should use TCachedArray class,
may be simpler is to use TList or TCollection class


it may make things simpler.
0
 
sokpasCommented:
It seems that you have a problem not directly related to the code you just posted.
Does each array element have its own Lattice? Is it possible to create once a lattice object and then assign it to 2 or more LatticeCache.caches? If so freeing 2nd time the same object is trouble.
for instance
LatticeCache.caches[current_ID].LatticeAddress := Lattice;
LatticeCache.caches[current_ID+2].LatticeAddress := Lattice;

LatticeCache.caches[current_ID].LatticeAddress.Free();
LatticeCache.caches[current_ID+2].LatticeAddress.Free();

should produce error.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
Sergio_HdezConnect With a Mentor Commented:
As other have pointed, using Laticce: TLattice is not the same as LaticceAddress: ^TLattice, as the first method let you create the Lattice INSIDE the object, while the second forces you to create it and then assign it to the pointer, so you can make it twice with the same Lattice being pointed from 2 pointers.

Also, I would do this when freeing it (in both cases, object or pointer):

LatticeCache.caches[current_ID].Lattice.Free;
LatticeCache.caches[current_ID].Lattice:= Nil;

So you avoid freeing it twice (it does nothing if you try to free it twice) as long as it is not rteferenced by pointers in other objects.
0
 
reynaerdeAuthor Commented:
Well, thanks for your advices, but still I'm having the same problem. I tried debugging some more and think I have pinpointed the problem, but I don't understand what is happening. Consider the following:

LatticeCache := TCachedDataArray.create(5);

  for Teller := 0 to 2 do
  begin
    Lattice := TLattice.create(700,700);
    LatticeCache.caches[Teller].LatticeAddress := @Lattice;
  end;

  showmessage('All created');

  if LatticeCache.caches[0].LatticeAddress = LatticeCache.caches[1].LatticeAddress then
    showmessage('hey!');

Am I comparing the 2 addresses here? If so, they are the same, which is strange because I called  Lattice := TLattice.create(700,700); twice..right?
Maybe I am getting a pointer to the address of the Lattice pointer? If so, how can I get the address of where Lattice is pointing TO?
It would, however, explain why I get an error when I execute the following(on the second iteration):

  for Teller := 0 to 2 do
  begin
    showmessage('Freeing: '+inttostr(Teller));
    LatticeCache.caches[Teller].LatticeAddress.Free();
  end;
0
 
sokpasConnect With a Mentor Commented:
Wrong,
>  for Teller := 0 to 2 do
>  begin
>    Lattice := TLattice.create(700,700);
>   LatticeCache.caches[Teller].LatticeAddress := @Lattice; <======= Here The address is the same!
>  end;
>
>  showmessage('All created');
>
>  if LatticeCache.caches[0].LatticeAddress = LatticeCache.caches[1].LatticeAddress then
>    showmessage('hey!');
>
>Am I comparing the 2 addresses here? If so, they are the same, which is strange because I called  >Lattice := TLattice.create(700,700); twice..right?

You just assign a pointer to the address of lattice  wich is the same in both times. So you just have the last object created (and pointed by Lattice) to all the pointers in LatticeCache. you should
 LatticeCache.caches[Teller].LatticeAddress := Lattice^;
The way you do it to be correct.
0
 
Slick812Connect With a Mentor Commented:
hello  reynaerde, I look your question here and the code in your last comment -

for Teller := 0 to 2 do
  begin
    Lattice := TLattice.create(700,700);
    LatticeCache.caches[Teller].LatticeAddress := @Lattice;
  end;

and I really thought it should work, it looked like correct pascal syntax to me, however your comment made me try it, and to my suprize, ,  my code did the same as your code (I used a TStringList instead of the TLattice, thinking the TLattice might be wonky). .
I then tried this code, without a FOR loop -

type
  PStringList = ^TStringList;

var
i: Integer;
caches : array of PStringList;
StrL1: TStringList;
begin
SetLength(caches, 5);


StrL1 := TStringList.Create;
caches[0] := @StrL1;
ShowMessage(IntToStr(Integer(@StrL1)));
StrL1 := nil;  // I thought set to nil would cancel the first create
StrL1 := TStringList.Create;
caches[1] := @StrL1;
ShowMessage(IntToStr(Integer(@StrL1)));
  //shows the same ADDY in both Showmessages?

if caches[0] = caches[1] then
  ShowMessage(' pointers Are Equal');
  // showed this message


for i := 0 to 1 do
  caches[i].Free; // access violation here
end;

I could not beleive it, and I can not explain it, I do not remember having this before?
I can not find anything about this in the Delphi Help, but I am not sure where to look in there?


So, (?) It looks like if you repeat an object Creation with the same variable, it does not create a new object, it just replaces the variable with the previous creation object, but I do NOT know anything about this, or any why or how of the object NON-creation.

anyway, here is some code with what I think is more correct delphi syntax -


type
  PStringList = ^TStringList;

var
i: Integer;
caches : array of PStringList;
begin

for i := 0 to 1 do
  begin
  New(caches[i]);
  caches[i]^ := TStringList.Create;
  ShowMessage(IntToStr(Integer(caches[i])));
  end;

this seems to work for me
I am guessing that this is an experiment for you? I think most (at least me) would not use the

TCachedData = class(TObject)
  LatticeAddress : ^TLattice;
  constructor create();
end;

but I would use

TCachedData = class(TObject)
  Lattice : TLattice;
  constructor create();
end;

actually I would NOT have only the  "Lattice : TLattice;"  in an Object, since it will work by it's self. . . but I guess that there are other things that you will place in this object. . .
0
 
reynaerdeAuthor Commented:
@sokpas:
Your code gives a compilation error since I'm assigning the dereferenced value of Lattice to a pointer type(LatticeAddress : ^TLattice;)
What I figured myself(and I think this is what you were trying to say) is:
Lattice is a pointer, which points to a different location each time BUT @Lattice is pointing to the address of the pointer itself, thus Lattice^ just is a dereference to the last object assigned to it.

@slick812:
Your way works for me too, but still it seems strange to me:

I. new(LatticeCache.caches[Teller].LatticeAddress);
II. LatticeCache.caches[Teller].LatticeAddress^ := Lattice;

So, now I'm allocating memory for a pointer in <I> and then assigning the Lattice object to the dereferenced value of
LatticeCache.caches[Teller].LatticeAddress in <II>.. quite confusing to me...!!?!


And yes, you are right, the TCachedData holds some other objects but I left them out to simplify the code.
It is sort of an experiment, but in my mind it seemed the most logical thing to do, since I already had TLattice in place and later on needed to keep some of these objects. And to my understanding, Lattice IS in fact a pointer to the memory with the TLattice object. Basically what I do is:

- I am creating an object 'Lattice' on which I run some procedures. I then need to store that for later retrieval and repeat the same process with a new Lattice.
- In step 2 I select the stored Lattices I need and dispose of the rest. Then repeat these steps.

Anyways, the next problem is with the memory amounts I need which seem abnormally large to me, but I'm creating a new question for that.
0
 
reynaerdeAuthor Commented:
You will both get points, I just don't want to close this question yet since I'd really like to know the logic behind:

I. new(LatticeCache.caches[Teller].LatticeAddress);
II. LatticeCache.caches[Teller].LatticeAddress^ := Lattice;

:)
0
 
Slick812Commented:
I looked at your other question just a little, and I beleive you may not use correct syntax with -

 for Teller1 := 0 to Dimensie1 + (2*bufferzone -1) do
    begin // vul lattice 1e dimensie
      for Teller2 := 0 to Dimensie2 + (2*bufferzone -1) do  // vul lattice 2e dimensie
      begin
        Temp_Cell := TCell.create();
        self.cell[Teller1,Teller2] := Temp_Cell;
      end; // einde vul lattice 2e dimensie
    end; // einde vul lattice 1e dimensie
end;


you might should Leave OUT the  Temp_Cell  variable and try this

 for Teller1 := 0 to Dimensie1 + (2*bufferzone -1) do
    begin // vul lattice 1e dimensie
      for Teller2 := 0 to Dimensie2 + (2*bufferzone -1) do  // vul lattice 2e dimensie
      begin
        self.cell[Teller1,Teller2] := TCell.create();
      end; // einde vul lattice 2e dimensie
    end; // einde vul lattice 1e dimensie
end;
0
 
Slick812Connect With a Mentor Commented:

TCell = class(TObject)
  status : cell_status;
  to_update : cell_status;
  lifetime: word;
  resist: byte;
  activated: bool;
  constructor create();
end;

and I really wonder about why you placed this in and object, you do not have ANY functions or procedures in this object, I think it is more effiecient to just use a Record, maybe -

TCell = record
  status : cell_status;
  to_update : cell_status;
  lifetime: word;
  resist: byte;
  activated: bool;
  end;
0
All Courses

From novice to tech pro — start learning today.