Solved

Use of object within a record declaration

Posted on 2009-04-15
10
334 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 6

Expert Comment

by:JosephGlosz
Comment Utility
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
Comment Utility
I second that as well... :D
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:brenlex
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
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…

762 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

11 Experts available now in Live!

Get 1:1 Help Now