Irrlicht 1.8. Application not closing and memory leak...

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by robmar »

No its okay because in the destructor, if ReferenceCount was ever grabbed, the global is reduced too.
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by robmar »

With your fixes I´m also down to 3 on the global counter.

So 3 objects are not being deleted somewhere.

Here is the code for the refcounter class that I´m using:-

Code: Select all

 
// Copyright (C) 2002-2010 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
#ifndef __I_IREFERENCE_COUNTED_H_INCLUDED__
#define __I_IREFERENCE_COUNTED_H_INCLUDED__
 
#include "irrTypes.h"
 
namespace irr
{
    //! Base class of most objects of the Irrlicht Engine.
    /** This class provides reference counting through the methods grab() and drop().
    It also is able to store a debug string for every instance of an object.
    Most objects of the Irrlicht
    Engine are derived from IReferenceCounted, and so they are reference counted.
 
    When you create an object in the Irrlicht engine, calling a method
    which starts with 'create', an object is created, and you get a pointer
    to the new object. If you no longer need the object, you have
    to call drop(). This will destroy the object, if grab() was not called
    in another part of you program, because this part still needs the object.
    Note, that you only need to call drop() to the object, if you created it,
    and the method had a 'create' in it.
 
    A simple example:
 
    If you want to create a texture, you may want to call an imaginable method
    IDriver::createTexture. You call
    ITexture* texture = driver->createTexture(dimension2d<u32>(128, 128));
    If you no longer need the texture, call texture->drop().
 
    If you want to load a texture, you may want to call imaginable method
    IDriver::loadTexture. You do this like
    ITexture* texture = driver->loadTexture("example.jpg");
    You will not have to drop the pointer to the loaded texture, because
    the name of the method does not start with 'create'. The texture
    is stored somewhere by the driver.
    */
 
    class IRRLICHT_API IReferenceCounted //export from dll when compiling/import when linking with dll
    {
public:
 
        //! Constructor.
        IReferenceCounted()
            : DebugName(0), ReferenceCounter(1)
        {
#if defined(_DEBUG)
            GlobalRefCounter++;     // As a static var, its set to zero, adn shared between all classes
#endif
        }
 
        //! Destructor.
        virtual ~IReferenceCounted()
        {
#if defined(_DEBUG)
                --GlobalRefCounter;
#endif
 
            _IRR_DEBUG_BREAK_IF( ReferenceCounter > 1 )     // Check if deleted and grabs still existing
        }
 
        //! Grabs the object. Increments the reference counter by one.
        /** Someone who calls grab() to an object, should later also
        call drop() to it. If an object never gets as much drop() as
        grab() calls, it will never be destroyed. The
        IReferenceCounted class provides a basic reference counting
        mechanism with its methods grab() and drop(). Most objects of
        the Irrlicht Engine are derived from IReferenceCounted, and so
        they are reference counted.
 
        When you create an object in the Irrlicht engine, calling a
        method which starts with 'create', an object is created, and
        you get a pointer to the new object. If you no longer need the
        object, you have to call drop(). This will destroy the object,
        if grab() was not called in another part of you program,
        because this part still needs the object. Note, that you only
        need to call drop() to the object, if you created it, and the
        method had a 'create' in it.
 
        A simple example:
 
        If you want to create a texture, you may want to call an
        imaginable method IDriver::createTexture. You call
        ITexture* texture = driver->createTexture(dimension2d<u32>(128, 128));
        If you no longer need the texture, call texture->drop().
        If you want to load a texture, you may want to call imaginable
        method IDriver::loadTexture. You do this like
        ITexture* texture = driver->loadTexture("example.jpg");
        You will not have to drop the pointer to the loaded texture,
        because the name of the method does not start with 'create'.
        The texture is stored somewhere by the driver. */
        //void grab() const { ++ReferenceCounter; }
#if defined(_DEBUG)
        void grab() const { ++ReferenceCounter; ++GlobalRefCounter; }
#else
        void grab() const { ++ReferenceCounter; }
#endif
        //! Drops the object. Decrements the reference counter by one.
        /** The IReferenceCounted class provides a basic reference
        counting mechanism with its methods grab() and drop(). Most
        objects of the Irrlicht Engine are derived from
        IReferenceCounted, and so they are reference counted.
 
        When you create an object in the Irrlicht engine, calling a
        method which starts with 'create', an object is created, and
        you get a pointer to the new object. If you no longer need the
        object, you have to call drop(). This will destroy the object,
        if grab() was not called in another part of you program,
        because this part still needs the object. Note, that you only
        need to call drop() to the object, if you created it, and the
        method had a 'create' in it.
 
        A simple example:
 
        If you want to create a texture, you may want to call an
        imaginable method IDriver::createTexture. You call
        ITexture* texture = driver->createTexture(dimension2d<u32>(128, 128));
        If you no longer need the texture, call texture->drop().
        If you want to load a texture, you may want to call imaginable
        method IDriver::loadTexture. You do this like
        ITexture* texture = driver->loadTexture("example.jpg");
        You will not have to drop the pointer to the loaded texture,
        because the name of the method does not start with 'create'.
        The texture is stored somewhere by the driver.
        \return True, if the object was deleted. */
        bool drop() const
        {
            // someone is doing bad reference counting.
            _IRR_DEBUG_BREAK_IF(ReferenceCounter <= 0)
            _IRR_DEBUG_BREAK_IF(GlobalRefCounter <= 0)
 
 
            if ( --ReferenceCounter == 0 )      // On most CPUs the Dec instruction sets the zero flag, so this should compile efficiently
            {
                delete this;        // Will reduce global counter in destructor
                return true;
            }
 
#if defined(_DEBUG)
            --GlobalRefCounter;
#endif
 
            return false;
        }
 
        //! Get the reference count.
        /** \return Current value of the reference counter. */
        s32 getReferenceCount() const
        {
            return ReferenceCounter;
        }
 
        //! Get the reference count.
        /** \return Current value of the reference counter. */
        s32 getGlobalReferenceCount() const
        {
            return GlobalRefCounter;
        }
 
        //! Returns the debug name of the object.
        /** The Debugname may only be set and changed by the object
        itself. This method should only be used in Debug mode.
        \return Returns a string, previously set by setDebugName(); */
        const c8* getDebugName() const
        {
            return DebugName;
        }
 
    protected:
 
        //! Sets the debug name of the object.
        /** The Debugname may only be set and changed by the object
        itself. This method should only be used in Debug mode.
        \param newName: New debug name to set. */
        void setDebugName(const c8* newName)
        {
            DebugName = newName;
        }
 
    private:
 
        //! The debug name.
        const c8* DebugName;
 
        //! The reference counter. Mutable to do reference counting on const objects.
        mutable s32 ReferenceCounter;
 
public:
        static s32 GlobalRefCounter;
    };
 
} // end namespace irr
 
#endif
 
 
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by REDDemon »

I failed at creating a class-based reference counter.

I used std::map<debugname,refcount>

the problem was that when referencecounter contrustructor is called, debug name was not setted. So I had to manually change all constructors in irrlicht to accept debug name directly in IReferenceCounter constructor.

This system still doesn't work correctly for certain classes, probably there's a less invasive way to make it working. no idea about that).

Anyway due to per - frame allocations, classbased reference counter is very slow. (helloworld with opengl running at 2-3 fps). Few of the anomalies reported was for example the videomodelist, but robmar already found that XD. (anyway thi system is higly bugged. For ISceneNode it reports a leak proportional to number of frames. While IsceneNOde has no leak, at least in hello world).
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by robmar »

not sure I understand what the problem is. Using the IReferenceCounted class posted above I´ve been able to debug all my code and found a grab and two drops I forgot to sort out.

I´m at 0 memory leaks!!

I hadn´t understood the memory deletion handling system well, but now I´ve got it!
Some "Irrlicht memory handling for dummies" would have been real useful! :)
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by REDDemon »

great :)
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by CuteAlien »

I've added some code to make hunting such leaks a little easier (had to do it myself last 2 days).
With current svn you can set _IRR_COMPILE_WITH_LEAK_HUNTER_ in IrrCompileConfig.h and then add the following code at the end of your application (or after closing and dropping the last device):

Code: Select all

 
#ifdef _IRR_COMPILE_WITH_LEAK_HUNTER_
    irr::core::array<const irr::IReferenceCounted*> objectsLeftOver = irr::LeakHunter::getReferenceCountedObjects();
    if ( !objectsLeftOver.empty() )
    {
       // Set a breakpoint here - or use a loop instead and watch all objects left over. Or add an assert.
        int dbg = 1;    
    }
#endif
 
In objectsLeftOver you have then all objects not yet dropped and can watch them in a debugger for example.
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
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by robmar »

.. but how can you know which objects they are, from looking at the bytes to determine the class...?

I mean this is an array of IRefs, is there a way to know what the IRef was connected to, which class?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by CuteAlien »

The debugger does show you the real class.
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
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by robmar »

In Visual Studio? But forgive my at time muddled mind, hmmm may I should change my forum name..., sorry, but your array is of the IRef class type, which is the base class of all Irr objects, so how does the debugger know the final child class, ISceneNode.. etc?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by CuteAlien »

You're asking me difficult stuff ... :-) Answer is that I'm not 100% certain, but I think it finds the information because IReferenceCounted has virtual functions. For those to work each object derived has a pointer to it's virtual function table (it's hidden from the user, but all your class-objects which are derived from a class with virtual functions are 4-byte larger on 32-bit systems because of this pointer). And I guess the debugger still knows which virtual function table belongs to which class.

Or in short - it just works. And yeah, I've only tested this in VS so far, not sure right now if gdb (or C::B + gdb) supports that also - I hope so.

But even without it the code could help because Irrlicht does in debug set debug-names for most IReferenceCounted objects (which by the way adds another pointer to each such objects).
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
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Irrlicht 1.8. Application not closing and memory leak...

Post by robmar »

okay, I´m half convinced! I´ll give it a try next time I have a leak! :)

I sorted our all my leaks, well 4 of them, so for now I´m headache free... well, apart from having headaches over figuring how to get an animated face into irrlicht that looks as real as the nvidia samples!!
Post Reply