Maya: Deleting node doesn't call destructor directly - c++

I have a small problem with a custom node I created in Maya. If I do something like:
createNode -n "MyInstance" "MyNode";
delete "MyInstance";
It doesn't call the class destructor. But, if you do a new scene, open a new file, or do anything that forces the destruction of the current scene, the destructor is finally called.
The thing is that I have some memory allocations that I would like to clear right away instead of waiting until the end to actually clear them. Because they're not needed anymore, so they should be cleared.
I looked in the documentation, and I don't see any virtual functions I could override that would be called when the node is actually deleted, or a similar event. There's such function to track connection between attributes (actually using it in this case), but no such thing for delete.
So if any of you have an idea for a bypass, or a way to simulate this, please share!
Thanks.
W

So guys,
Finally found it. It's totally not where it's supposed to be. Autodesk has some weird way to do things.
Here it is:
void removeMyNode(MObject &node, void *clientData)
{
MFnDependencyNode nodeFn(node);
MGlobal::displayInfo(MString("Removal callback node: ") + nodeFn.name());
}
MDGMessage::addNodeRemovedCallback(removeMyNode, "MyNode", NULL, &status);
So, if a node is deleted, this callback is actually called. Still, I would have preferred a way to do this directly within the node definition by overriding a function.
Thanks to everyone that took a look at this question. Hope this could help some of you eventually!

Related

QGestureRecognizer automatically destroyed by QGestureManager?

I have recently experienced exit code 255 in my Qt 5.7 application. This happened right after I added my custom QGestureRecognizer. I have debugged into the Qt's sources and I came to the conclusion that the QGestureManager automatically disposes of all QGestureRecognizer instances. The line that causes the issue is inside the destructor of widget where the recognizer is created and registered:
Demo::~Demo() {
// delete other stuff
delete recognizer;
}
The thing is QGestureRecognizer doesn't support (at least according to the documentation and by looking at the constructor's signature) the parent-child relationship in Qt since it's not derived from QObject (or any subclass of that fundamental Qt class). This means that one cannot assign a parent to the its constructor hence QCustomGestureRecognizer recognizer = new QCustomGestureRecognizer (this) isn't possible. Continuing this line of thought this means that one has to manually trigger the destructor by calling delete recognizer. Or so I thought...
At the end of the life of my application the QGestureManager is called. In there there is a list of recognizers called m_recognizers. It contains a bunch of the built-in recognizers (such as the one for the Tap gesture) along with the registered custom recognizer (in my case it was registered as 257). The destructor of QGestureManager iterates through the list and deletes its entries.
When the delete recognizer line is present I get a segmentation fault when qDeleteAll(...) (for the m_recognizers) reaches the custom recognizer's entry since it attempts to delete something that has already been deleted.
After I commented out the delete recognizer line in my widget's destructor I no longer face the issue however I'm still uncertain if I'm not breaking my code somewhere. The exit code is not (as expected) a 0 but the information on how recognizers are disposed is completely missing from the official documentation.
Has anyone encountered this problem? I'm not excluding the possibility that the issue arises from some other part of my code although it seems quite unlikely considering that it appears when the default QWidget destructor is called. As per C++ standard when inheriting a class first the subclass' destructor is called (in my case this is the Demo custom widget - no issues there) and then the base class.
If you use
Qt::GestureType QGestureRecognizer::registerRecognizer(QGestureRecognizer *recognizer)
the System does take ownership of the object and you should not delete it yourself.
Excerpt from the Documentation:
The application takes ownership of the recognizer and returns the
gesture type ID associated with it.

Dereferencing a pointer to a frame that doesn't exist anymore

I have MessagesViewer frame that I want to control the uniqueness of,
with this piece of code:
MessagesViewer* m_pMsgViewer = NULL;
void Application::ShowMessagesViewer()
{
if (m_pMsgViewer == NULL)
{
m_pMsgViewer = new MessagesViewer(
wxGetApp().GetContainer()->GetAppData()->GetMessages()
);
}
else
{
m_pMsgViewer->FillPage(wxGetApp().GetContainer()->GetAppData()->GetMessages());
m_pMsgViewer->SetFocus();
}
}
But when I call this for the first time, m_pMsgViewer starts to refer to valid data in the memory. When I close MessagesViewer frame, it destroys it automatically, but the pointer is still referencing to old address, and I can't control destroying the frame from this client code.
How can I dereference a pointer to destroyed frame?
#bogdan already proposed a good solution, but there is another, even more automatic one: store your frame pointer in wxWeakRef<> instead. I.e. keep exactly the same code as now but replace the declaration with
wxWeakRef<MessagesViewer> m_pMsgViewer;
The weak reference will be automagically reset to NULL when the window is destroyed.
One solution is to set m_pMsgViewer back to nullptr when MessagesViewer is closed. A safe way to do that is to add a handler for wxEVT_CLOSE_WINDOW to your frame. For example, add the following code to MessagesViewer's constructor:
Bind(wxEVT_CLOSE_WINDOW, [](wxCloseEvent& evt)
{
m_pMsgViewer = nullptr;
evt.Skip();
});
evt.Skip() lets the event propagate further to the default handler provided by wx.
This simple example assumes that m_pMsgViewer is a global variable. If it's actually contained within the Application object, you'll have to add some way to access it.
The obvious alternative of adding such code to MessagesViewer's destructor is not a very good idea, as the actual destruction of the MessagesViewer object is delayed according to the docs, so it would be theoretically possible for Application::ShowMessagesViewer() to call FillPage() on a frame that has been closed and marked for destruction but not actually destroyed yet.
Handling the close event resets the pointer early on, thus avoiding the problem above.
You need to mark somehow that MessagesViwer has been destroyed and cannot be referenced any more. This means some extra info in addition to m_pMsgViewer.

How to safely call disconnect in Qt?

I am using qt 4.8.
And I write something like:
Myclass* A = input_class_pointer;
...
disconnect(A,SIGNAL(A_S()),B,SLOT(B_S()));
However, sometimes when I call this, I found that the actual instance of A is already deleted somewhere else. And now the pointer A is pointing into rubbish. And by calling the disconnect, it resulted a crash.
Is there any simple way to solve this which require minimum amount of modification in the code?
I have many similar issues...
As mentioned in comments above there ways to detect whether the instance of QObject was deleted or not. One is QPointer which is a type of weak-pointer. But the problem is that we want to know when that QObject gets deleted, not after the fact. So, there is QObject::destroyed signal for that.
connect(A, destroyed(QObject*), this, onWatchObjDestroyed(QObject*));
And in your class code that watches some objects:
void MyClass::onWatchObjDestroyed(QObject* pObj)
{
// do certain disconnects for pObj, etc. if needed (?)
}

VSTGUI: Conventions for editor::open and editor::close

While writing a new vst-plugin using VSTGUI I'm really struggling with how to use the library, and most progress is made from guessing and debugging after (because there really is no documentation besides the million lines and ygrabit, which states little more than the obvious).
So far it's going good, but my last contribution to the project involved threads which made the design a little bit more problematic. Specifically, I'm working on a set of textlabels in a container (doing non-atomic operations) and these may (and obviously does) get destructed without my knowledge, when a user closes the window.
Even adding checks right before changing elements might still be a problem. So I actually need to control the lifetime of these objects (which is fine) except when they are shown in a CViewContainer, it automatically assumes ownership.
I have no idea how to write the backbone of the editor, so i used a program called VSTGUIBuilder for this, and appended (and basically rewrote) what i needed. However, since all 'views' you can work with requires either a parent or a systemwindow, you cannot instantiate any views/controls before reaching the AEffEditor::Open() function, which is called whenever your window is popped up.
And the AEffEditor::close() method is called whenever the window is closed. Now, the vstguibuilder put a
delete frame;
inside the AEffEditor::close() method which suggests you rebuild and dispense all resources on every open and close. Can this really be true? And if it is, is there no way i can protect my container's contents (which for details is a vector< CTextLabel *>) from getting deleted mid-function? It's no problem to dispose of it afterwards, I'm just worrying about segfaults while changing it.
Using mutexes and the such is really the last resort (if the call is coming from the host), I don't want to hang the host in any case if my code faults and never releases.
Edit:
I ended up finding a solution which is not so elegant, but works safely. Here's the code in the worker function:
while(bLock) {
Sleep(0);
}
bLock = true;
if(msgs.empty())
return;
/*
Prevent someone deletes our lines in close().
we create a copy of the container to be 100% sure
and increase the reference count, so we can safely
work with our own container and we 'forget' them
afterwards, so they will be deleted if needed.
This ensures that close AND open can be called
meanwhile we are working with the lines
*/
bDeleteLock = true;
// also the copy constructor should work as expected here
// since we are working with pointers, we still reference the same content.
auto copy_lines = lines;
for each(auto line in copy_lines) {
line->remember();
}
bDeleteLock = false;
...
for each(auto line in copy_lines) {
line->forget();
}
cont->setDirty();
bLock is another 'mutex' that protects a message queue, which this function will print out. bDeleteLock protects the process of copying the line container and 'remembering' them, and instantly releases if afterwards. Both are declared as volatile bools, shouldn't that be enough? Here's the close() method btw.
void CConsole::Close() {
// locking lines while copying them over in a container we can work with
while(bDeleteLock)
Sleep(0);
//waiting for bLock is not needed because it wont get deleted.
if(!visible) //if we are not visible it's our responsibility to remove the view
delete cont;
lines.clear();
}
Ahh, VSTGUI, that brings back some dark memories. ;) But seriously, yes, you will probably have to use a mutex to prevent the host from hanging. Having to instantiate everything when the window reopens seems kind of silly, but you can see many plugins do just that.
One potential workaround is to use a shared memory segment for cached view data, and then pass a reference to the location back to your plugin

C++ Ref Count Changes While Destructing Object

I've got a private ref count inside the class SharedObject. SharedObject is a base class for other classes, for example Window. Window is the base class of Editor.
When the ref count reaches 0, because of calling SharedObject::Release(), the SharedObject deletes itself. First we get to the Editor destructor, which shows that the this pointer contains m_refs == 0, but when we get to the Window destructor it is suddenly 1, and when we reach the SharedObject destructor, it is still 1.
I put a breakpoint on the SharedObject::IncRef() method, and it was never called while this happened.
What the?
Build with optimizations off, and set a memory breakpoint on your m_refs.
Seems like you have memory leak somewhere, maybe even long before this destruction occurs. I use Alleyoop to find leaks. Can help, won't hurt to have that out of the way.
Do you use multiple threads? Maybe it's due to some raw pointer somewhere being grabbed by other thread during destruction.
On a side note, I recommend using boost::intrusive_ptr - very convinient pattern for handling addrefs and releases in shared objects that helps to be consequent with it, but this probably won't solve your problem unless you have a real mess in your code ;)