Solved

question about pointers

Posted on 2001-08-23
1
168 Views
Last Modified: 2010-04-06
Suppose I have a record like such:

Type
  pMsgRec = ^msgRec;
  msgRec = record
  msgID:array [0..23] of char;
  msgType: String;
end;

Now suppose I have a TList that I want to add msgRec to.

Lets say in a program I assign some values to msg:

msg:pMsgRec;
messages : TStringList;

for i:= 0 to 4 do
begin
   New(msg);  //Do I need to do this?
   strcopy(msg.msgID,'Some info');
   msg.msgType := 'NEW';
   messages.add(msg);
   Dispose(msg);  //Do I need this?
end;



Now lets say I want to get a message back out

for i:= 0 to messages.count-1 do
begin
   msg := messages.item(i);  
   //do some work
   msg := nil;      // Do I need this?
end;

I'm confused on
1.  after insertion into the tlist I have a list of pointers. Where does the actual record exist? (I assume it exists since I used New()).

2. If I dispose(msg) does the item placed in the list no longer point to a memory location? Or if I'm not suppose to dispose(msg), does the next iteration through the loop assign it to another record and the previous one is lost?

3. When reading it out do I need to set it to nil before getting the next record out of the list?


4. Why use pointers at all. Can't I just fill the TList with records?


Thanks,
Rut






0
Comment
Question by:rutledgj
[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
1 Comment
 
LVL 20

Accepted Solution

by:
Madshi earned 75 total points
ID: 6419662
Okay, let's do the pointer twist again, lala...  :-)

First let's begin with some basics about pointers and memory etc: Each process in 32bit Windows has its own memory/address context from $00000000 - $FFFFFFFF. That means you can access any of the memory in this area, it does belong to your process and you don't touch the memory of another process (well, in win9x the high half of this area is in fact shared between all processes, but let's forget that for now). However, all this memory is protected by default. If you access it, the CPU raises an access violation. If you now try to allocate a memory block, Windows looks through all your private memory context to find a block, which is not in use yet. If it finds one (it always will, if you don't have a memory leak and do not waste memory), this block gets marked as in use now. In that moment it is not longer protected, you can access it now. Of course you need to know, which block Windows has reserved for you. So the allocation function returns the beginning address of this block. The beginning address of a block is called "pointer".

Okay, the function "New" is an allocation function, that means, it reserved a memory block in your process' memory context and stores the start address of this block into the pointer variable you gave in. Because "New" is a quite intelligent function, it knows how big the block has to be, depending of the pointer type you give in. In your example "New" automatically allocated "sizeOf(msgRec)" bytes.
Now, as long as you don't undo the allocation (with Dispose), the memory block remains reserved and doesn't get used by anyone else. The pointer in your local "msg" variable is nothing but the start address (e.g. $12345678). The connection between this variable and the allocated memory block is quite lose. You can have 5 variables point to this memory block or none. It doesn't really matter. The memory block stands for itself, as long as noone disposes it again.

Now let's look at your code and your questions:

Type
 pMsgRec = ^msgRec;
 msgRec = record

You should follow the common naming conventions, that is name types with a capital leading "T" like "TMsgRec" and pointer types with a leading "P" like "PMsgRec".

msg:pMsgRec;
messages : TStringList;

for i:= 0 to 4 do
begin
  // until now the variable "msg" is not initialized
  // that means, it contains a random value
  // in other words: it points to a random memory block
  // if you now would access this random memory block
  // you would either overwrite important data or
  // access a protected block, resulting in an access violation
  // the question is: What do you want to do?
  // the answer: You want to fill a new TMsgRec record
  // so you first have to reserve a memory block for a new record
  New(msg);

  // okay, "New" allocated a memory block in the correct size
  // a pointer to this new memory block is stored in "msg"
  // now we can fill this memory block
  // I prefer the "pointer^.element" syntax
  // because this shows, we're dealing with a pointer
  // which points to an allocated record
  strcopy(msg^.msgID,'Some info');
  msg^.msgType := 'NEW';

  // now we add the start address of the allocated memory block to our list
  // as I said before, the connection between the pointer
  // variable and the memory block itself it lose
  messages.add(msg);

  // DO NOT CALL Dispose HERE! Dispose would release the memory block
  // but we still need the memory block!
end;

for i:= 0 to messages.count-1 do
begin
  // only for explanation: the following line just
  // takes a start address from the list and stores it
  // into a local pointer variable
  // we deal only with 4 byte ordinal addresses here
  // this has not really much to do with the record itself, yet
  msg := messages.item(i);  

  // you can do "msg := nil" here, that is clear the local variable
  // but it doesn't make much sense, it's just a 4 byte ordinal address
  // as was said before, the connection between the pointer and the record is lose
end;

What you did not do yet is free the records again. When you don't need the whole list anymore you should do something like this:

for i := 0 to messages.count - 1 do begin
  msg := messages[i];
  Dispose(msg);
end;
messages.Free;

>> 1.  after insertion into the tlist I have a list of pointers. Where does the actual record exist? (I assume it exists since I used New()).

I hope I explained that in the big text above.

>> 2. If I dispose(msg) does the item placed in the list no longer point to a memory location?

It still points to a memory location, but the memory location is not marked as "in use" anymore. That can end up in that another portion of your program reuses this memory block or it can end up in that the memory block gets protected again. In that case any access to it would produce an access violation.

>> 3. When reading it out do I need to set it to nil before getting the next record out of the list?

Clearing a local 4 address ordinal variable has no effect on the memory block. Why should it?

>> 4. Why use pointers at all. Can't I just fill the TList with records?

TList only supports pointers (that is 4 byte address ordinal variables). If you have D4-6, you might want to look at dynamic arrays, which is something like a list of records. In that case you don't have much to do with pointers anymore. (Well, internally dynamic arrays are again realized by pointers, but Delphi hides that from you as good as possible).

Regards, Madshi.

P.S: Wow, a lot of writing for 75 points...   :-/
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Delphi : could not find program, '...exe' 2 215
Printing problem 2 111
Delphi IDE crash without error message ... 7 120
Tvertscrollbox like a whatsapp layout 5 53
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
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…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

726 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