Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 379
  • Last Modified:

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 !?
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
brenlex
Asked:
brenlex
  • 4
  • 4
  • 2
1 Solution
 
HypoCommented:
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
 
HypoCommented:
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
 
JosephGloszCommented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
JosephGloszCommented:
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
 
HypoCommented:
I second that as well... :D
0
 
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?
0
 
JosephGloszCommented:
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
 
HypoCommented:
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
 
JosephGloszCommented:
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
 
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.  
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

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

  • 4
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now