Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Memory Leak with TagData and GeDialog

 Post Reply Post Reply
Author
Message
valkaari View Drop Down
Member
Member
Avatar

Joined: 2009 Dec 08
Online Status: Offline
Posts: 21
Post Options Post Options   Quote valkaari Quote  Post ReplyReply Direct Link To This Post Topic: Memory Leak with TagData and GeDialog
    Posted: 2018 Jan 11 at 7:49am

User Information:

Cinema 4D Version:   R19 
Platform:      Mac OSX  ; 
Language(s):     C++  ;   

---------

Hi everyone, 

I'm using a GeDialog attached to a tag, catching MSG_EDIT to open it. So far so good.
Everything run as i wish, but when I modify parameters on the tag itself i have memory leak.

I've tried to isolate the problem creating an exemple as simple as possible to reproduce the problem.

In the exemple, i've used GetDDescription() to create the UI but the problem is the same with .res/.h/.str

This is where it get strange :
 - If i play with several parameters except the CheckBox  --> no memory leak.
 - If i play with several parameters and the CheckBox --> memory leak.
 - If i only play with the checkbox i got no leak. (even if i got several checkbox)

 - If i remove the GeDialog variable i got no leak and using a pointer to the dialog doesn't change anything.

I've check the way i initialise the Checkbox but even without using GeData(true) and only true it doesn't change anything.


The main.cpp and h, there nothing except the call to registerplugin and resource.Init()

In the exemple, the MYDIALOG class got nothing, but i didn't found anything there that could help.
I've include everything in one file (except the main.cpp)

I removed all other plugins to be sure.

If anybody got a hint.


//  memleak.cpp

#include "c4d.h"
// test ID
#define PLUGIN_ID 1000002
enum {
    
    MY_DYN_POINT_NUMBER = 1000,

    MY_DYN_BOOL,
    MY_DYN_BOOL_ONE,
    MY_DYN_BOOL_TWO,
    MY_DYN_SPLINE_OUTPUT,
    
    MY_DYN_REAL,
    MY_DYN_REAL_SLIDER,
    MY_DYN_ANOTHER_REAL,
    
    MY_BUTTON_ID,

    
    
};

class MYDIALOG : public GeDialog
{
    
    
};


class MyTag : public TagData
{
    
    INSTANCEOF(MyTag, TagData);

private:
    MYDIALOG dlg;
    
public:
    virtual     Bool Init(GeListNode* node);
    virtual     void                Free(GeListNode* node);
    virtual     Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags);
    static      NodeData*           Alloc (void) { return NewObjClear(MyTag);}
    
};

Bool MyTag::Init(GeListNode *node)
{
    
    node->SetParameter(MY_DYN_POINT_NUMBER, GeData(120), DESCFLAGS_SET_0);

    node->SetParameter(MY_DYN_BOOL, GeData(true), DESCFLAGS_SET_0);

    node->SetParameter(MY_DYN_SPLINE_OUTPUT, GeData(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE), DESCFLAGS_SET_0);
    
    node->SetParameter(MY_DYN_REAL, GeData(1.0), DESCFLAGS_SET_0);
    node->SetParameter(MY_DYN_ANOTHER_REAL, GeData(5.0), DESCFLAGS_SET_0);
    node->SetParameter(MY_DYN_REAL_SLIDER, GeData(500.0), DESCFLAGS_SET_0);
    
//    dlg = NewObjClear(MYDIALOG);
    
    return true;
}

void MyTag::Free(GeListNode *node)
{
//    DeleteObj(dlg);

}


Bool MyTag::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)
{
    
    if (!description->LoadDescription(Tbase))
        return false;
    
    
    const DescID* singleid = description->GetSingleDescID();
    DescID cid;
   
    
    

    
    // point number ------------------------------------------------------
    
    cid = DescLevel(MY_DYN_POINT_NUMBER, DTYPE_LONG,0);
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(DTYPE_LONG);
        bc.SetString(DESC_NAME, "Dyn point number");
        bc.SetInt32(DESC_SCALEH, 1);
        bc.SetInt32(DESC_MIN, 0);
        bc.SetInt32(DESC_MAX, 1000);
        bc.SetInt32(DESC_STEP, 1);
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }
    // bool  ------------------------------------------------------
    cid = DescLevel(MY_DYN_BOOL, DTYPE_BOOL, 0);
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BOOL);
        bc.SetString(DESC_NAME, "dyn bool");
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }
      // spline  ------------------------------------------------------
    cid = DescLevel(MY_DYN_SPLINE_OUTPUT, CUSTOMDATATYPE_SPLINE, 0);
    
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(CUSTOMDATATYPE_SPLINE);
        
        bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_SPLINE);
        bc.SetString(DESC_NAME, "dyn weight");
        bc.SetBool(SPLINECONTROL_GRID_H, true);
        bc.SetBool(SPLINECONTROL_GRID_V, true);
        bc.SetBool(SPLINECONTROL_VALUE_EDIT_H, true);
        bc.SetBool(SPLINECONTROL_VALUE_EDIT_V, true);
        bc.SetFloat(SPLINECONTROL_X_MIN, 0);
        bc.SetFloat(SPLINECONTROL_X_MAX, 1);
        bc.SetFloat(SPLINECONTROL_Y_MIN, 0);
        bc.SetFloat(SPLINECONTROL_Y_MAX, 1);
        
        
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }
    
    // real ------------------------------------------------------
    
    cid = DescLevel(MY_DYN_REAL, DTYPE_REAL, 0);
    
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(DTYPE_REAL);
        
        bc.SetString(DESC_NAME, "dyn Real");
        bc.SetInt32(DESC_SCALEH, 1);
        bc.SetInt32(DESC_MIN, 0);
        bc.SetInt32(DESC_MAX, 1000);
        bc.SetInt32(DESC_STEP, 1);
        bc.SetInt32(DESC_UNIT, DESC_UNIT_METER);
        
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }
    
    
    
    // another real ------------------------------------------------------
    cid = DescLevel(MY_DYN_ANOTHER_REAL, DTYPE_REAL, 0);
    
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(DTYPE_REAL);
        
        bc.SetString(DESC_NAME, "dyn another Real");
        bc.SetInt32(DESC_SCALEH, 1);
        bc.SetInt32(DESC_MIN, 0);
        bc.SetInt32(DESC_MAX, 10);
        bc.SetFloat(DESC_STEP, 0.1);
        
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }
    
    
    
    // real slider  ------------------------------------------------------
    
    cid = DescLevel(MY_DYN_REAL_SLIDER, DTYPE_REAL, 0);
    
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(DTYPE_REAL);
        
        bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_REALSLIDER);
        bc.SetString(DESC_NAME, "dyn Real Slider");
        bc.SetInt32(DESC_SCALEH, 1);
        bc.SetInt32(DESC_MIN, 0);
        bc.SetInt32(DESC_MAX, 1000);
        bc.SetInt32(DESC_STEP, 1);
        bc.SetInt32(DESC_UNIT, DESC_UNIT_METER);
        
        // slider settings
        bc.SetFloat(DESC_MINSLIDER, 250);
        bc.SetFloat(DESC_MAXSLIDER, 750);
        
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }

    // Button ------------------------------------------------------
    
     cid = DescLevel(MY_BUTTON_ID, DTYPE_BUTTON,0);
    
    if (!singleid || cid.IsPartOf(*singleid, nullptr))
    {
        BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BUTTON);
        bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON); // done with default data type ?
        bc.SetString(DESC_NAME, "Push me");
        bc.SetInt32(DESC_ANIMATE, DESC_ANIMATE_OFF);
        bc.SetBool(DESC_SCALEH, true);
        description->SetParameter(cid, bc, DescLevel(ID_TAGPROPERTIES));
    }
    

    
    flags |= DESCFLAGS_DESC_LOADED;
    
    
    return SUPER::GetDDescription(node, description, flags);
}





Bool RegisterMemLeakTest(void);

Bool RegisterMemLeakTest()
{
    
    return RegisterTagPlugin(PLUGIN_ID, "testing Leak", TAG_EXPRESSION | TAG_VISIBLE   , MyTag::Alloc, "", nullptr, 0);
}

 



and the memory leaks (the first one is always there)
Memory Leaks Detected:
../../../frameworks/core.framework/source/maxon/basearray.h (223): Memory leak of 16 bytes () at 0x114abb500
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/richard/genesis/ge_smart_link.cpp (465): 2 Memory leaks of 40 bytes (, first leak at 0x13376c800)
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/richard/genesis/ge_smart_link.cpp (584): 2 Memory leaks of 72 bytes (, first leak at 0x108d61580)
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/tilo/cgui/cgui_coffeedialog.cpp (1421): 2 Memory leaks of 624 bytes (, first leak at 0x136e2ec00)
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/tilo/cgui/cgui_coffeedialog.cpp (1432): 2 Memory leaks of 400 bytes (, first leak at 0x134569300)
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/tilo/cgui/cgui_coffeedialog.cpp (2968): 2 Memory leaks of 1368 bytes (, first leak at 0x12e82f700)
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/tilo/cgui/cgui_main.cpp (114): 2 Memory leaks of 600 bytes (, first leak at 0x136e2ef00)
/perforce_buildsystem_osx/compile-osx-3-release/depot/release/19.0/modules/c4dplugin/source/src/tilo/cgui/cgui_main.cpp (157): 2 Memory leaks of 488 bytes (, first leak at 0x134712280)
8 blocks not freed


Edited by valkaari - 2018 Jan 11 at 8:03am
Back to Top
Yannick Puech View Drop Down
Forum Moderator
Forum Moderator


Joined: 2011 Apr 13
Location: Spain
Online Status: Offline
Posts: 1131
Post Options Post Options   Quote Yannick Puech Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jan 12 at 3:50am
Hi,

A NodeData plugin can't hold a GeDialog like a CommandData.
An object plugin is created multiple times (on the undo stack for instance) and is also managed in different threads than the main. Remember GUI operations have to be done in the main threads.

The solution is to have a CommandData holding the dialog. Then from the tag's MSG_EDIT use CallCommand() to invoke it.
MSG_EDIT is run on the main thread so GUI operations can be done. Same for MSG_DESCRIPTION_COMMAND with buttons in descriptions.

Catch EVMSG_CHANGE from the dialog's CoreMessage() to refresh it according to the tag's state.



MAXON
Developer Support
Back to Top
valkaari View Drop Down
Member
Member
Avatar

Joined: 2009 Dec 08
Online Status: Offline
Posts: 21
Post Options Post Options   Quote valkaari Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jan 12 at 8:36am
Ok changing all this.

i'm storing data in the tag (not in a basecontainer)
Using SpecialEventAdd() to send a pointer to my data after the callCommand seems to work. Is it ok to do that ? 

edit : 
even with those change i still got memory leak when i'm playing with checkbox 


Edited by valkaari - 2018 Jan 12 at 8:51am
Back to Top
Yannick Puech View Drop Down
Forum Moderator
Forum Moderator


Joined: 2011 Apr 13
Location: Spain
Online Status: Offline
Posts: 1131
Post Options Post Options   Quote Yannick Puech Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jan 12 at 9:06am
Originally posted by valkaari

Using SpecialEventAdd() to send a pointer to my data after the callCommand seems to work. Is it ok to do that ? 
Yes that's fine.




MAXON
Developer Support
Back to Top
valkaari View Drop Down
Member
Member
Avatar

Joined: 2009 Dec 08
Online Status: Offline
Posts: 21
Post Options Post Options   Quote valkaari Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jan 16 at 12:46am
after changing the data stored in the tag, i've killed the memory leak. Thanks for the support :)
Back to Top
Yannick Puech View Drop Down
Forum Moderator
Forum Moderator


Joined: 2011 Apr 13
Location: Spain
Online Status: Offline
Posts: 1131
Post Options Post Options   Quote Yannick Puech Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jan 16 at 1:35am
You're welcome. Glad the memory leak is solved.



MAXON
Developer Support
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.109 seconds.