Toolplugin Crash When Close Cinema 4D



  • hi,
    i write a toolplugin, alloc a baseobject in InitTool() ,the baseobject pointer is toolplugin private member. free baseobject in FreeTool .
    it works fine when switch tool .but when i close cinema 4d, myplugin will be crash and show this crash.PNG ,
    i thought maybe cinema 4d free all object auto when close(i know it will not case crash,but just try)? so i use "if(myobject != nullptr)"check if free baseobject,but it unuseful, crash again. Where did I go wrong?
    hope your help!

    class mytool : public ToolData
    {
       ......
    private:
      BaseObject* myobject;
    }
    
    Bool mytool::InitTool(BaseDocument * doc, BaseContainer & data, BaseThread * bt)
    {
      this->myobject = BaseObject::Alloc(Onull);
      doc->InsertObject(myobject,  nullptr,  false);
      return true;
    }
    
    void mytool::FreeTool(BaseDocument * doc, BaseContainer & data)
    {
       BaseObject::Free(myobject);
    }
    


  • Hi mike, thanks for reaching out us.

    With regard to your code, there's an ownership issue: actually once you insert an object in the document, Cinema 4D takes ownership on the object and if you want to destroy it you need first to take ownership back (in this case with the BaseObject::Remove() method)

    On top of this, in your ToolData::InitTool() method, the BaseObject::InsertObject() method is provided with a wrong sequence of parameters.

    I suggest you to consider something like:

    Bool PC_11560_ToolData::InitTool(BaseDocument * doc, BaseContainer & data, BaseThread * bt)
    {
    	// just check the passed params
    	if (!doc || !bt)
    		return false;
    	
    	// allocate and check for validity
    	myobject = BaseObject::Alloc(Onull);
    	if (!myobject)
    		return false;
    	
    	// insert object in the document
    	doc->InsertObject(myobject,  nullptr,  nullptr, false);
    	return true;
    }
    
    void PC_11560_ToolData::FreeTool(BaseDocument * doc, BaseContainer & data)
    {
    	// check the pointer validity and take back ownership by removing from the document
    	if (myobject)
    		myobject->Remove();
    	
    	// dispose the object and free the memory
    	BaseObject::Free(myobject);
    	myobject = nullptr;
    }
    

    Finally if you want to insert an object upon user interaction there I recommend a simpler CommandData and if you need to store a reference please make proper use of BaseLink (I leave it to you)

    Regard, Riccardo



  • From the docs:

    void InsertObject 	( 	BaseObject *  	op,
    		BaseObject *  	parent,
    		BaseObject *  	pred,
    		Bool  	checknames = false 
    	)
    
    Parameters
        [in]	op The object to insert into the document. The document takes over the ownership of the pointed object.
    

    Which means, once you have inserted the object, you should not free it! The document will do so, when being destroyed.



  • @C4DS thank you for your answer.follow your answer, i think if i can detect currect project close, the problem will be solve, could your tell me how to detect currect project close in toolplugin or scenehook? hope your help : )



  • unsafe way , just use "try catch(...)",skip error, if any better solution?



  • DO NOT try to solve your problems by fixing the side effects.
    DO solve your problem by removing the cause.



  • @C4DS maybe use scenehook detect tool switch, and trigger tool "messgae" to free mybaseobject is a better way ?it can avoid the crash,and tool also work normally



  • Hi mike, thanks for reaching out us.

    With regard to your code, there's an ownership issue: actually once you insert an object in the document, Cinema 4D takes ownership on the object and if you want to destroy it you need first to take ownership back (in this case with the BaseObject::Remove() method)

    On top of this, in your ToolData::InitTool() method, the BaseObject::InsertObject() method is provided with a wrong sequence of parameters.

    I suggest you to consider something like:

    Bool PC_11560_ToolData::InitTool(BaseDocument * doc, BaseContainer & data, BaseThread * bt)
    {
    	// just check the passed params
    	if (!doc || !bt)
    		return false;
    	
    	// allocate and check for validity
    	myobject = BaseObject::Alloc(Onull);
    	if (!myobject)
    		return false;
    	
    	// insert object in the document
    	doc->InsertObject(myobject,  nullptr,  nullptr, false);
    	return true;
    }
    
    void PC_11560_ToolData::FreeTool(BaseDocument * doc, BaseContainer & data)
    {
    	// check the pointer validity and take back ownership by removing from the document
    	if (myobject)
    		myobject->Remove();
    	
    	// dispose the object and free the memory
    	BaseObject::Free(myobject);
    	myobject = nullptr;
    }
    

    Finally if you want to insert an object upon user interaction there I recommend a simpler CommandData and if you need to store a reference please make proper use of BaseLink (I leave it to you)

    Regard, Riccardo



  • @r_gigante Thank you for your answer! it s all fine : )


Log in to reply