Killing reference counted objects

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Starterz
Posts: 27
Joined: Thu Apr 02, 2009 2:45 am

Killing reference counted objects

Post by Starterz »

//! As you can see this code will fail:

Code: Select all

SomeType* obj->createSomeObj(); //! It mean 'new' or 'smgr->add' etc.. 
obj->delete(); 
if(obj) obj->doSmth()...
You can remove() of course instead delete and it's correct, then add obj=0;
That code will not fails but...
If our object have getReferenceCount()>1 it'll NOT WILL BE DELETED and
we can have memory leak..

Well just define this:

Code: Select all

#define KILL(irrobject) \ 
{\ 
  if(irrobject)\ 
  {\ 
    s32 ref=irrobject->getReferenceCount();\ 
    while(--ref>0) irrobject->drop();\ 
    irrobject->remove(),irrobject=NULL;\ 
  }\ 
} 
O'k don't blame me.. just try it works!

An improve that KILL macros is preventing "not exist object" error's type.
(Usual if you drop,remove or delete an object and call it later you'll got one.)

Now don't worry of it just do simple check in your code:

Code: Select all

SomeType* obj->createObj; 
KILL(obj) 
......... 
//! Even if we KILL somewhere our object yet. 
//! Doing a simple check: 
if(obj) obj->doSmth(); 
This code will work anyway

And of course you must not use KILL(object) if your code
still needs an object. If you used object->grab() etc..

Sorry for my bad english, friends.
Last edited by Starterz on Wed Nov 17, 2010 6:47 pm, edited 6 times in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Sorry, but your KILL macro should never be needed nor ever be used. Writing a macro for setting a variable to 0 after a drop would be fine. But the following line is a guarantee for disaster:

Code: Select all

while(--ref>0) irrobject->drop();\ 
and that following this line by a 'remove' even works without crash rather surprises me.

In short - reference counting is there to help you with having _correct_ reference counts and releasing object memory correctly. If you ever get problems with this, then it's because you didn't grab() drop() correct in your code. Your KILL macro will completely mess up this mechanism and can lead to unexplainable crashes in other parts of the engine.

And a small hint for future posts - you can use a code flag in this forum to make code better visible (just look at the buttons above the box when you enter the text) :-)

edit: Please don't think of it as criticism, we're glad when people are active, just a chance for improving future post. And in this mood - further improvement is using better topic titles. Try to use titles where people can from reading title already figure out what the thread is about. So instead of "%)) A little bit sweet hack :" something like "Macro for killing reference counted objects" is better.

Btw.. you can still rework your post and fix everything up with the "edit" button :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Starterz
Posts: 27
Joined: Thu Apr 02, 2009 2:45 am

Post by Starterz »

CuteAlien wrote:... But the following line is a guarantee for disaster:

Code: Select all

while(--ref>0) irrobject->drop();\ 
CuteAlien wrote:and that following this line by a 'remove' even works without crash rather surprises me.
Don't be surprised!

Code: Select all

    while(--ref>0) irrobject->drop(); 
//! Here ref. counter is exactly 1. 
    irrobject->remove(); 
//! Here Irr engine drop() an object, so ref. counter is exactly==0. 
//! At last Irr engine delete object at all. See remove() method. 
Well, I have not a problems with grab(),drop() in my oun code.
But sometimes it helps see "Terrain pager".

Of course I know that "KILL macro will completely mess up this mechanism" but using of it is correct when You know what You do..

"And of course you must not use KILL if your code
still needs an object. If you used object->grab() etc.."

Anyway yes you right it's better use grab() drop() remove() it's more correct
Last edited by Starterz on Wed Nov 17, 2010 6:55 pm, edited 7 times in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Ah ok, I see why the remove() part works now :-)

But you mix up 2 concepts there. drop() is about memory management. remove() on the other hand is not about memory management but about removing the object from a certain structure (for example the SceneGraph) and only calls another drop() internally because the SceneGraph has a reference.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Starterz
Posts: 27
Joined: Thu Apr 02, 2009 2:45 am

Post by Starterz »

CuteAlien wrote: But you mix up 2 concepts there. drop() is about memory management. remove() on the other hand is not about memory management...
Hope I'm not

O'k let us see why I don't use only string:

Code: Select all

while(ref-->0) irrobject->drop();

but use two strings:

Code: Select all

   while(--ref>0) irrobject->drop(); 
   irrobject->remove();


Because 'SceneGraph' !
I think You calls so Parent-Children mechanism (?)
As we can see drop() method just delete an object
when ref. counter is 0.
Other hand remove() method do this AND ERASE object from Children
AND (*object)->Parent = 0;
So can You show a code or example when Irr engine will crash after
this manipulations?
Last edited by Starterz on Wed Nov 17, 2010 6:56 pm, edited 6 times in total.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Starterz wrote:Of course I know that "KILL macro will completely mess up this mechanism" but using of it is correct when You know what You do...
You should still never mess with the reference count. If you drop an object more times than you grab it, the program will almost certainly crash later since another object will be unaware of this and call drop() on a pointer that now points to a deleted (and therefore nonexistent) object.

Dropping an object more times than you grab it is never correct. If doing so causes problems, you have a bug somewhere in your code.
Starterz
Posts: 27
Joined: Thu Apr 02, 2009 2:45 am

Post by Starterz »

Correct:
slavik262 wrote: If you drop an object more times than you grab it, the program will almost certainly crash later..
Uncorrect:
slavik262 wrote: "You should still never mess with the reference count."
Why? I do what I want..
slavik262 wrote:"since another object will be unaware of this and call drop()"
Why do you believe that MY ANOTHER OBJECT "call drop()" on deleted obj. pointer?
If I just check pointer before drop() delete() or remove() every time.

Code: Select all

if(object) object->drop();
See KILL macros:
irrobject->remove(),irrobject=NULL;
The pointer is NULL after deleting!

My code never drop an object more times than I grab it.

Other subject is (! Let's see) I never tell use KILL instead
normal Irr memory menagment..
I just say it can be use when you whant just REALY KILL an object.
Never do this if another part of your programm needs it!
Or if somewhere another object can drop() it without any checks!
I know every object of my big big code AND I SURE WHEN KILL smth.
Just come in Russia I live, and you'll see that we can do things
not only we "should" to do It's more fun in life!

p.s. Thanks anyway!
Last edited by Starterz on Wed Nov 17, 2010 6:49 pm, edited 5 times in total.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

In Soviet Russia, references count you!

Anyways, I wasn't talking about your code. Irrlicht maintains lots of internal references which you have absolutely no control over . These are the reason you need to respect reference counting.

Calling drop just once on your object will always kill it unless Irrlicht has other references to it internally. If the latter is true, dropping it more than you have grabbed it will break things. I'm not going to argue this with you. Feel free to ignore me, but enjoy the segfaults.
Starterz
Posts: 27
Joined: Thu Apr 02, 2009 2:45 am

Post by Starterz »

slavik262 wrote: In Soviet Russia, references count you!
You'll don't believe but You 2 is counted by KGB

NO I NEVER IGNOR YOU!
Just can you explain to me please where (what concretaly structure what string?)
"Irrlicht has other references to it internally" if an object
complitly removed from Scene Graph ?

As we know class IReferenceCounted is a base class
of most objects of the Irrlicht Engine.

when this method (called by remove internally):

Code: Select all

     bool drop() const 
      { 
         // someone is doing bad reference counting. 
         _IRR_DEBUG_BREAK_IF(ReferenceCounter <= 0) 

         --ReferenceCounter; 
         if (!ReferenceCounter) 
         { 
            delete this; 
            return true; 
         } 

         return false; 
      }
Do 'delete this;'. Then in remove()

Code: Select all

Children.erase(it);
Since there is no more
"other references to it internally" or how do You think?
Last edited by Starterz on Wed Nov 17, 2010 6:49 pm, edited 5 times in total.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

For scene nodes, Irrlicht won't maintain any more references if you remove it from the scene graph, so you'll be fine. Just know that Irrlicht maintains references to things like textures, shader callbacks, etc., and killing those with your KILL macro may cause problems when Irrlicht goes to drop them on device->drop().
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

For example you might use the scenenode in another place with another variable. Then setting this variable to 0 won't help you as the other variable will never be noticed and will now point to invalid memory. Or you could use the scenenode for more than just rendering, for example you might use it also in an AnimatedMeshSceneNodeEmitter, then this won't work anymore.

The point of reference counting is to ensure that you do not release memory unless there's no variable left that needs this memory. And with this macro you break that mechanism.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Starterz
Posts: 27
Joined: Thu Apr 02, 2009 2:45 am

Post by Starterz »

slavik262 wrote: Just know that Irrlicht maintains references to things like textures, shader callbacks, etc., and killing those with your KILL macro ...
Nop.

Such "things like textures, shader callbacks" hasn't no remove() metod!
So no one can "killing those with (my) KILL macro"..

Candidates for KILLing are: IGUIEement and yes - ISceneNode..

Let's KILL everything! :)

So of cause it was just an experiment and if to be a serious it's better
slavik262 wrote: "never mess with the reference count".
CuteAlien nothing to say, it's true!

Thank's friends! You absolutely right! Topic can be closed.
Mikhail9
Posts: 54
Joined: Mon Jun 29, 2009 8:41 am

Post by Mikhail9 »

Your ideas are intriguing to me and I wish to subscribe to your newsletter.
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

I see there are more advanced persons here.....

So can somebody please tell me something. Suppose i load and animated mesh (IAnimatedMesh). The mesh is in the memory, but it's not yet used by a scene node. Later i add it to a node ( addAnimatedMeshSceneNode ( IAnimatedMesh mesh) ). Does the reference count increase automatically, or i should "grab" it from my code?

Again, if i remove the scene node, the mesh will still be loaded into the memory. Should it drop it manually? Or removing it from the scene will automatically decrease the reference counter and when it reaches zero it will be automatically erased ?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

If you pass reference counted objects to functions in Irrlicht which continue using the object, then they will increase the reference count. So you usually don't have to care about that and also don't have to drop unless you created an object with a "create" functions.

But one exception is that there are also caches which keep an additional reference - so objects which are used by no other structure will usually still be in the mesh-cache. You can access that with ISceneManager::getMeshCache () and enforce removing meshes also from there.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply