Use of object within a record declaration

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 !?
   TMyRecord = record
         RecID: Longint;
         RecType: TMyRecType;
         RecData: TMyObject;

    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?
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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.

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... :)
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).


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...  
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

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.   :)
I second that as well... :D
brenlexAuthor Commented:
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?
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...
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.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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.
brenlexAuthor Commented:
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.  
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.