I was testing my latest builds (using JUCE 5.3.2), and saw my host (Cubase 10) crash when I closed my project, without quitting Cubase, and with my plugin still open. The crash log shows this:
I don’t recall seeing this before, and don’t know of any changes that I have made that are related to the timer. My processor and editor classes both derive publicly from Timer, so they should destroy themselves normally, shouldn’t they? Is there something I need to do in my classes’ destructors to prevent the timers from firing and leading to this crash? Do I have to loop until the timer callbacks exit (checking a member flag that I set on entry and reset on exit to the timer callbacks)?
EDIT: I added stopTimer() calls at the start of my destructors, and also added guards around the code in the timer callbacks to ensure they aren’t re-entered, and even added a loop in the destructor to make sure the timer callbacks had finished before proceeding with the destructor code, but none of those helps. I still get JUCE Time crashes when closing my project in Cubase 10 with my plugin open.
Have you tried attaching the debugger to Cubase while it’s running (not tried it myself but it should be possible, only Pro Tools has problems with debuggers I’ve found…)? That should show you what line is causing the problem
If you’re using Xcode you can select “Edit Scheme” for the VST/VST3 scheme you’re using and then set the executable to the /Applications/Cubase.app bundle. Or if you want to start Cubase first then attach, there’s the “Debug -> Attach To Process” menu
I found it. Not sure exactly how it caused a crash, but running from the command line showed me a bunch of leaked objects stemming from our look&feel-derived class. Turns out we were not calling reset() on that pointer, so it was leaking. Apparently (guessing), this also led to code in it being called somehow when the plugin was being torn down. Now the leak is plugged and the crash is gone. Whew!
You shouldn’t have to call reset(), it is called automatically, when the stack is rolled back.
If you have a unique_ptr, that leaks if you don’t call reset(), that indicates that the stack/object that owns the unique_ptr itself isn’t destroyed.
Calling for JUCE_DECLARE_NON_COPYABLE_AND_LEAK_DETECTOR or JUCE_ADD_LEAK_DETECTOR.
The editor class (derived from AudioProcessorEditor) is the one that owns this pointer. If it’s not being destroyed, then that would be a host bug, right? Or is the processor class supposed to delete it? It is created in createEditor(), but simply returned from that function, not stored as a member in my derived processor class. Is that not correct?
I already have the macro JUCE_DECLARE_NON_COPYABLE_AND_LEAK_DETECTOR(myeditorclass) at the end of my AudioProcessorEditor-derived class. That class, however, is two generations down from AudioProcessorEditor, and the class between then does not have that. Does that class need that also (despite the fact it does not contain any of these std::unique_ptr members)?
However, I just noticed that my view components that are members of my editor (also as std::unique_ptr<>) all set the pointers to nullptr in the destructor, rather than calling reset() on them. Should I be doing that (instead)?
No, indeed. The host owns the editor and is responsible to delete that, especially to do so before the processor is deleted. This is especially crucial, since the processor reference in the editor becomes invalid, once the processor is deleted.
But that means also IMHO, that it seems unlikely, that a host would keep an editor around without the corresponding processor.
That is identical, afaik. There is no need to change that.
I found that this is not fixed by that change. When quitting Cubase (10.0.20.141), it properly destroys the plugin’s editor component. But when simply closing the project, if the plugin window is open, then it crashes after leaking everything related to our LookAndFeel object. (I don’t actually know who created all these leaked objects, but there are many. Our LookAndFeel object is the only one I know the source of.)
When debugging, after stepping through all of those leak assertions, the stack trace gets reduced to just “start” and then the crash, with no indication of any associated C++ code at all.
EDIT: I have reported this to the Steinberg/Yamaha beta team, and am downloading a newer build to see if it fixes the issue.