Solved

Difference between address and pointer

Posted on 2004-10-21
199 Views
Last Modified: 2010-04-05
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!





0
Question by:reynaerde
    11 Comments
     
    LVL 6

    Expert Comment

    by:vadim_ti
    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
     
    LVL 1

    Expert Comment

    by:sokpas
    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
     
    LVL 6

    Assisted Solution

    by:Sergio_Hdez
    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
     

    Author Comment

    by:reynaerde
    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
     
    LVL 1

    Assisted Solution

    by:sokpas
    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
     
    LVL 33

    Assisted Solution

    by:Slick812
    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
     

    Author Comment

    by:reynaerde
    @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
     

    Author Comment

    by:reynaerde
    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
     
    LVL 33

    Accepted Solution

    by:
    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
     
    LVL 33

    Expert Comment

    by:Slick812
    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
     
    LVL 33

    Assisted Solution

    by:Slick812

    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

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Anonabox PRO Tor & VPN Router

    PRO is the most advanced way to fortify your privacy and online anonymity by layering the Tor network with VPN services. Use both together or separately, and without needing to download software onto your devices.

    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…
    Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
    how to add IIS SMTP to handle application/Scanner relays into office 365.
    Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

    933 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

    Need Help in Real-Time?

    Connect with top rated Experts

    17 Experts available now in Live!

    Get 1:1 Help Now