Solved

Use of object within a record declaration

Posted on 2009-04-15
10
353 Views
Last Modified: 2013-11-23
I have been looking at a third party's code and have found an occurence of a user-defined class declaration (RecData in the example) within a record !?
eg.
   TMyRecord = record
         RecID: Longint;
         RecType: TMyRecType;
         RecData: TMyObject;
    end;

    TMyRecType =(rtTypeOne, rtTypeTwo, etTypeThree);

...where TMyObject has its own constructors/destructors/properties/methods etc

I am quite sure this is bad practice, as I have never exercised this approach before.  However the occurence of this record is quite prevalent in the existing code and I do not fully understand the impact of having such a scenario -- though I suspect it is contributing to some memory loss (not picked up by 3rd party tools) over time.

Has anyone come across this before?
0
Comment
Question by:brenlex
  • 4
  • 4
  • 2
10 Comments
 
LVL 12

Expert Comment

by:Hypo
ID: 24149091
Hi,
It might be bad practice, but I would not say that it is not invalid programming as long as the code keeps track of the object in the record, and make sure that it is created and destroyed whenever it should be. If this record is only used as an internal structure by a managed list class, which has control of add and removal of items, then that class could create and destroy the objects in a correct fashion, and it would never pose a problem.

regards
Hypo
0
 
LVL 12

Expert Comment

by:Hypo
ID: 24149173
I meant to say that "I would not say that it is invalid programming..." in the first sentence above... I hate it when I rephrase something and then it comes out the opposite of what I intended... :)
/Hypo
0
 
LVL 6

Expert Comment

by:JosephGlosz
ID: 24151203
I agree with Hypo, except that it is not "bad practice" in any way.  There is nothing with having an array or list of objects, which is essentially what you have here.

Just remember to think of the object declaration inside the record as just a pointer. It means nothing until you instantiate the object.  So, if you have an array of these records, say for example,  

var MyRecord: array [1..100] of TMyRecord;  

then you'll have to do a

MyRecord[x].RecData := TMyObject.Create; for each x you plan to use.

And if you use a dynamic list instead of any array, then of course the same thing still applies (as per Hypo above).

 (and a subsequent destroy, as Hypo says - without the destroy, you'd have a memory leak).

Joseph

p.s. pls don't award any "assist" pts here for me in case you were tempted; I just wanted to add my 0.02 worth...  
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
LVL 6

Expert Comment

by:JosephGlosz
ID: 24151235
I meant to say "there is nothing WRONG with having an array or list of objects"  I hate it when my fingers get lazy and skip typing out whole words.   :)
0
 
LVL 12

Expert Comment

by:Hypo
ID: 24151403
I second that as well... :D
0
 

Author Comment

by:brenlex
ID: 24151508
I have discovered however that I am unable to (nil and) free an instance of TMyObject once created and passed in a method parameter... I can only set it to 'nil', otherwise I get an exception... is there a reason for this?  If I can only set the object pointer to nil without a free being possible, will this memory be recouped later?
0
 
LVL 6

Expert Comment

by:JosephGlosz
ID: 24151605
In some cases, nil'ing an object will also free the memory, for example, in the case of THTTPRIO components. Which you specifically cannot "free" or there'll be an exception.

But most of the time, not calling an object's destructor method will cause a memory leak.

In this, I can't guess as to why you have this probably. Typically a 'FreeAndNil' works great.  Might depend on how you are passing this object, and where you are creating it (it's scope) etc.  You might have to post actual examples...
0
 
LVL 12

Accepted Solution

by:
Hypo earned 500 total points
ID: 24151623
If you get an exception when you try to free the the object, this can depend on one of four things (as I can think of right now)...
1: The pointer to the TMyObject has already been freed from another part of the code, which means that you are trying to free already freed memory. Quite likely if you can breakpoint and see that the exception actually triggers exactly when you try to free the object.
2: The object is freed by you, but another part of the code is also working with the object, and that causes an exception. Not so likely if the exception triggers exactly at the point where you are freeing the object; that would imply that another thread is working with the object.
3: The TMyObject is an interfaced object which is referenced counted, and shall therfore not be freed as an ordinary object, but instead only be released by setting the pointer to nil and thereby letting delphi reference count and handle its destruction.
4: The Creator of TMyObject is supposed to free the object, and gets notified when the object is destroyed by you, and then starts executing tasks that should only be executed when the destruction was triggered by the owner itself.

There are probably more scenarios that I just can't think of right now, but these are some situations that can be the problem if you get an exception when you try to free an object.

regards
Hypo
0
 
LVL 6

Expert Comment

by:JosephGlosz
ID: 24151698
Yes. And regarding Hypo's #4: if the Create method has an Owner parameter, you may need to set this to "nil" or "self" (to force you to explicitly destroy the object, or let the 'parent' object do it) or to the appropriate owner.
0
 

Author Comment

by:brenlex
ID: 24151857
I have a suspicion that point #2 (re: cross thread use) is the cause of my exception when attempting a free -- and in itself seems like the most likely cause of my memory leak.  Many thanks for your verbose input.  
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

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…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

820 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