Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Deconstructor of DUI element never gets called (Read 2720 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Deconstructor of DUI element never gets called

To register my DUI element with foobar I am using:
Code: [Select]
class uie_lyrics_dui : public ui_element_instance, public CWindowImpl<uie_lyrics_dui>
{

    uie_lyrics_dui(ui_element_config::ptr data, ui_element_instance_callback_ptr p_callback)
    {
    }

    ~uie_lyrics_dui()
    {
    }

};

class uie_lyrics_dui_element_myimpl : public ui_element_impl_withpopup<uie_lyrics_dui> {};

static service_factory_t<uie_lyrics_dui_element_myimpl> g_ui_element_myimpl_factory;


However the destructor "~uie_lyrics_dui()" never gets called. (discovered with a memory leak detector, verified with breakpoints).

This leads to memory leaks and I want to avoid that.
But how to do it?

The only possibility I see currently is to free once the window receives a WM_DESTROY message, but isn't there a better way to do it?

And why does the service factory never call the destructor?

Any help would be great

Deconstructor of DUI element never gets called

Reply #1
I think the destructor should be virtual.

Deconstructor of DUI element never gets called

Reply #2
I've already tried that, does not work :/

 

Deconstructor of DUI element never gets called

Reply #3
I have found the reason:

window_service_impl_t does not delete, but calls DestroyWindow() instead, im now researching about CWindowImpl


Edit:

Okay, normally , if using CWindowImpl, one would free/destruct on the DestroyWindow() call.

However, as my window is not using CWindowImpl, and i just relayed all messages from CWindowImpl to it, I decided to no longer inherit from CWindowImpl.

However, I still wanted to use ui_element_impl_withpopup from the ATLHelpers, so I have stripped all ATL code from these templates (all but the usage of CFlashWindow).
Modified code follows, in case somebody finds this useful.

Code: [Select]
template<typename TImpl, typename TInterface = ui_element> class my_ui_element_impl : public TInterface {
public:
    GUID get_guid() { return TImpl::g_get_guid();}
    GUID get_subclass() { return TImpl::g_get_subclass();}
    void get_name(pfc::string_base & out) { TImpl::g_get_name(out); }
    ui_element_instance::ptr instantiate(HWND parent,ui_element_config::ptr cfg,ui_element_instance_callback::ptr callback) {
        PFC_ASSERT( cfg->get_guid() == get_guid() );
        service_nnptr_t<ui_element_instance_impl_helper> item = new service_impl_t<ui_element_instance_impl_helper>(cfg,callback);
        item->initialize_window(parent);
        return item;
    }
    ui_element_config::ptr get_default_configuration() { return TImpl::g_get_default_configuration(); }
    ui_element_children_enumerator_ptr enumerate_children(ui_element_config::ptr cfg) {return NULL;}
    bool get_description(pfc::string_base & out) {out = TImpl::g_get_description(); return true;}
private:
    class ui_element_instance_impl_helper : public TImpl {
    public:
        ui_element_instance_impl_helper(ui_element_config::ptr cfg, ui_element_instance_callback::ptr callback) : TImpl(cfg,callback) {}

        GUID get_guid() {return TImpl::g_get_guid();}
        GUID get_subclass() {return TImpl::g_get_subclass();}
    HWND get_wnd() {return TImpl::get_wnd();}
    };
public:
    typedef ui_element_instance_impl_helper TInstance;
    static TInstance const & instanceGlobals() {return *reinterpret_cast<const TInstance*>(NULL);}
};

template<typename TClass>
class my_ImplementBumpableElem : public TClass {
private:
    typedef my_ImplementBumpableElem<TClass> TSelf;
public:
    TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD_WITH_INITIALIZER(my_ImplementBumpableElem, TClass, {_init();} )

    void notify(const GUID & p_what, t_size p_param1, const void * p_param2, t_size p_param2size) {
        if (p_what == ui_element_notify_visibility_changed && p_param2 == 0 && m_flash.m_hWnd != NULL) m_flash.Deactivate();
        __super::notify(p_what, p_param1, p_param2, p_param2size);
    }

    static bool Bump() {
        for(pfc::const_iterator<TSelf*> walk = instances.first(); walk.is_valid(); ++walk) {
            if ((*walk)->_bump()) return true;
        }
        return false;
    }
  ~my_ImplementBumpableElem() throw() {
        PFC_ASSERT(core_api::is_main_thread());
    
    m_selfDestruct = true;
        m_flash.CleanUp();

        instances -= this;
    }
private:

    bool _bump() {
        if (m_selfDestruct || m_hWnd == NULL) return false;
        //PROBLEM: This assumes we're implementing service_base methods at this point. Explodes if called during constructors/destructors.
        if (!this->m_callback->request_activation(this)) return false;
        m_flash.Activate(m_hWnd);
        return true;
    }
    void _init() {
        m_selfDestruct = false;
        PFC_ASSERT(core_api::is_main_thread());
        instances += this;
    }
    static pfc::avltree_t<TSelf*> instances;
    bool m_selfDestruct;
    CFlashWindow m_flash;
};


template<typename TImpl, typename TInterface = ui_element_v2> class my_ui_element_impl_withpopup : public my_ui_element_impl<my_ImplementBumpableElem<TImpl>, TInterface> {
public:
    t_uint32 get_flags() {return KFlagHavePopupCommand | KFlagSupportsBump;}
    bool bump() {return my_ImplementBumpableElem<TImpl>::Bump();}

};

template<typename TClass>
pfc::avltree_t<my_ImplementBumpableElem<TClass> *> my_ImplementBumpableElem<TClass>::instances;

static service_factory_t<my_ui_element_impl_withpopup<uie_lyrics_dui> > g_ui_element_myimpl_factory;