coll, objects and free method
Nov 2, 2010 at 11:29am
coll, objects and free method
I’m having a quite serious problem with coll dealing with A_OBJ atoms.
The thing is, it looks like coll in certains occasions (e.g., I duplicate the coll) tries to free the objects whose pointers it has stored. But most of the times those objects have already been freed, and this results either in a “freeobject: bad object” in the Max window (small problem), or a Max crash (big problem), or even a computer crash (huge problem).
Of course it doesn’t make much sense to me to store the objects in a coll; but it’s a possible patching mistake, and it should not have devastating consequences. Moreover, while I have experienced this problem with coll, I fear that other object might have the same behavior.
My question is: is there a way to prevent coll from freeing the object? E.g., is there a flag I can set somewhere saying that my class must not be freed? In this case, I could free it only when I need, by “manually” calling its former free method and then freeing the memory taken by the object… does this make sense?
Nov 3, 2010 at 9:18pm
In general you should not be passing A_OBJ atoms in a max patcher, or storing them in a coll. There is essentially zero support for these atoms in standard box objects. We use hashed symbolic names for Jitter matrices for this reason.
That said, there is an essentially undocumented API for object_retain(t_object *x), and object_release(t_object *x) for object reference counting similar to Obj C. It’s up to you to ensure that there will be no memory leaks, and there’s no guarantee that coll might reference said object after you’ve freed said object, since coll will not call object_retain(). Use them at your own risk.
Or better yet, register the object in a namespace via object_register, and send the object name around the patcher, resolving by client objects with object_findregistered(). This way no other objects will be using or referencing the A_OBJ directly except the ones you are writing.
This lets you safely use useful box classes like pack, zl, coll, etc. with your symbolic object references. If your object disappears while any of them still refer to said reference, it won’t be locatable from object_findregistered().
However, internal to your class, I thought you might also have a use for object_retain/release. For example one of your recent posts that showed creating a temporary atom array could have been made a little simpler with object_retain/release.
Nov 4, 2010 at 12:21am
In fact, because of the potentially great number of instances of my class, I don’t want to use symbols for naming or binding them – I fear they might clog up the symbol table. But I can do something not too different with numeric keys – I just need to set up a hash-table-like thing in order to deal with them, and then I can harmlessly pass them in the patcher as regular A_LONGs.
Some questions about object_retain/release, which look very useful to me:
Thank you very much, as always
Nov 4, 2010 at 4:05am
As for not bloating the symbol pool, you can use symbol_unique(), which after 10k symbols (@30 bytes each), will start reusing symbols from the unique symbol pool, so no further bloat than ~300k per application launch.
As for object_retain/release():
1. Yes, they are threadsafe.
Hope this helps.
Nov 4, 2010 at 8:30am
aah, I didn’t know about this thing of symbol_unique()
last questions about the reference counting system:
Nov 4, 2010 at 6:47pm
1. The details are subtle. I would simply match object_new() (or other constructor) with object_free() and object_retain() with object_release().
Essentially, object_release() may not free an object if object_retain() has never been called. It is dependent on some special extra object info which we allocate if certain extended features are being used. object_retain() forces this to happen, but other things like registering an object, adding object specific attributes, etc. can do this as well.
In future versions, we could make object_release() free even in the absence of calling object_retain() first, but such a situation hasn’t been required by our internal usage.
2. Unfortunately, there is currently no way to get the reference count. We can consider this for the future, but for now, you’ll need to manage this elsewhere somehow.
You must be logged in to reply to this topic.