Plugin leaks on Windows

Hi,

I have a quite strange behavior if I compile my plugin under Win7 64Bit
but treated as 32Bit plugin. Same happens in WinXP 32Bit…
It compiles w/o any problem but then it leaks dramatically while host
scans for the plugin. I got a massive number of leaks but the juce leak
detector does not specify the class that leaks ;-( It just says “Leaked object-> “!

It doesn’t leak at all if I compile it a standalone on Win 7 and it also
doesn’t leak at all if I compile both, plugin and standalone on MAC OSX Lion!
If my code would be massively broken why don’t I get a leak notification
after stopping debugging of my standalone app on Windows?

I tried to use VLD but this doesn’t say anything useful, just that Reaper
or Cubase leaked.

I have strongly used RAII technology but now I am at the end of my knowledge
and need some suggestions how I could isolate the culprit.

I am on latest git, downloaded by using

git clone --depth 1 git://juce.git.sourceforge.net/gitroot/juce/juce

BTW: If I use Introjucer to ask for module update, it always says that
the version 2.0.21 is already installed ;-(

Any helpful suggestion how you would investigate in this issue is highly appreciated!

Thanks
Joerg

how big are the leaks?

Every leak block is 16 bytes long and it counts up to 1753 leaks. Yeah, that is a massive number
but probably has to do with the huge number controls I have to create for my plugin.

[quote]but the juce leak
detector does not specify the class that leaks ;-( It just says “Leaked object-> “![/quote]

It’s impossible for the juce leak detector to not provide a name, so I think you must be either misreading the log or confusing it with some other kind of leak detector (?)

16 bytes, seems to be messages, i have always 2-3 of them, because the dll is unloaded before they are processed. Maybde your plugin/controls send massive messages (changeMessage/Timer/AsyncUpdater etc…), and the plugin is closed/unloaded before the messages are processed at scanning time.

This isn’t the juce-leak detector, it is the built-in VS leak detector (which is also very useful!)

sorry, my last sentence was wrong

Okay, my controls are derived from juce slider and button listener and I create and add them
to an OwnedArray. The UI then adds and make them visible and attach slider
listener to them and just removes these listener in the deconstructor when the UI gets destroyed.
That means the controls are always existing in the OwnedArray even if no plugin editor exists.
But I have also tested the plugin with “hasEditor = false” to avoid creating the plugin editor
w/o success. It still leaks…

Jules, the leak detector defenitelly says nothing about the leaked object. I also found it very odd
but it is the case. I am not in front of my dev computer but will provide a screen print later today.

ok, not sure, but i can imagine that components interacting with the message-thread, somehow. And if you running no message-thread (host doesn’t open the gui!?!), these is a potential problem, but thats just an assumption.

It’s not odd at all - the juce leak detector can only work with objects where it’s been explicitly declared in the class definition - it can’t catch general leaks caused by malloc or other allocators.

You originally said that the juce leak detector wasn’t printing a class-name, which would have been very odd! But in fact you’re just confusing it with the VS leak detector.

the vs-leak detektor doesn’t prompt "Leaked-Object"
http://msdn.microsoft.com/en-us/library/e5ewb1h3(v=vs.90).aspx

@jörg
i wouldn’t create any GUI-Objects when the Plugin-editor isn’t opened

Thank you guys.

@Jules
All of my classes have declared juce leak detector! I only use malloc in one class which is
the fifo storage for speed reasons but fifo is not involved here.
I have remove the include statement for VLD so it can’t be interfering but I will also go and deinstall VLD
completely, just for safety.

@chkn
Mmmh, then I would have to re-design the whole thing. May Jules can say something about that?

okay, here is a sample of the log just to show that the class name is missing.
This is not to blame you Jules, it might help to improve the leak detector and may tells you
what object leaks!

'reaper.exe': Loaded 'C:\Windows\SysWOW64\normaliz.dll', Cannot find or open the PDB file
'reaper.exe': Loaded 'C:\Windows\SysWOW64\iertutil.dll', Cannot find or open the PDB file
'reaper.exe': Loaded 'C:\Windows\SysWOW64\urlmon.dll', Cannot find or open the PDB file
JUCE v2.0.21
Detected memory leaks!
Dumping objects ->
{120505} normal block at 0x0600D1D0, 16 bytes long.
 Data: < p b            > D0 70 E3 62 01 00 00 00 00 00 00 00 88 C7 00 06 
{120445} normal block at 0x0600C800, 16 bytes long.
 Data: < p b            > D0 70 E3 62 01 00 00 00 00 00 00 00 88 C7 00 06 
{120382} normal block at 0x0600D108, 16 bytes long.
 Data: < p b            > D0 70 E3 62 01 00 00 00 00 00 00 00 E0 C7 00 06 
{120318} normal block at 0x0600D040, 16 bytes long.
 Data: < p b            > D0 70 E3 62 01 00 00 00 00 00 00 00 E0 C7 00 06 
{120254} normal block at 0x0600CD38, 16 bytes long.
 Data: < p b            > D0 70 E3 62 01 00 00 00 00 00 00 00 E0 C7 00 06 
{120182} normal block at 0x0600C858, 16 bytes long.
 Data: < p b            > D0 70 E3 62 01 00 00 00 00 00 00 00 E0 C7 00 06 
{120108} normal block at 0x0600BE18, 16 bytes long.
 Data: < p b        P   > D0 70 E3 62 01 00 00 00 00 00 00 00 50 BD 00 06

Those don’t look like c++ objects. Probably leaked messages like was suggested above.

Visual Leak Detector provides a much more detailed output… of course there is a large performance hit when using it, but I find the tool to be extremely helpful.

http://vld.codeplex.com/

Mmmh, I took VLD back into the game. Seems that a AsyncUpdater is involved…
It`s not well readable, sorry, but does it tell you something where I should look at?
chkn seems to be right but I have made the class where the OwnedArray with the controls lives derived from
Component and added the controls to it directly after creating. No change;-(

---------- Block 1939 at 0x071CDCD0: 52 bytes ----------
  Call Stack:
    c:\eigene_dateien\vst_development\juce\modules\juce_events\broadcasters\juce_asyncupdater.cpp (51): VCommanderVST.dll!juce::AsyncUpdater::AsyncUpdater + 0x7 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\mouse\juce_mouseinputsource.cpp (34): VCommanderVST.dll!juce::MouseInputSourceInternal::MouseInputSourceInternal + 0x33 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\mouse\juce_mouseinputsource.cpp (488): VCommanderVST.dll!juce::MouseInputSource::MouseInputSource + 0x2F bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\native\juce_win32_windowing.cpp (2910): VCommanderVST.dll!juce::Desktop::createMouseInputSources + 0x26 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\components\juce_desktop.cpp (32): VCommanderVST.dll!juce::Desktop::Desktop
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\components\juce_desktop.cpp (49): VCommanderVST.dll!juce::Desktop::getInstance + 0x25 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\lookandfeel\juce_lookandfeel.cpp (304): VCommanderVST.dll!juce::LookAndFeel::getDefaultLookAndFeel + 0x5 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\components\juce_component.cpp (2027): VCommanderVST.dll!juce::Component::getLookAndFeel
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_slider.cpp (1402): VCommanderVST.dll!juce::Slider::lookAndFeelChanged + 0x14 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_slider.cpp (1313): VCommanderVST.dll!juce::Slider::init
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_slider.cpp (1298): VCommanderVST.dll!juce::Slider::Slider
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_methodsandclasses.cpp (2706): VCommanderVST.dll!JK_Slider::JK_Slider + 0x37 bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_vccontrols.cpp (281): VCommanderVST.dll!JK_VCControls::createControls + 0x52 bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_vccontrols.cpp (62): VCommanderVST.dll!JK_VCControls::JK_VCControls
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_methodsandclasses.cpp (52): VCommanderVST.dll!JK_ApplicationManager::JK_ApplicationManager + 0x2B bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_filter.cpp (43): VCommanderVST.dll!JK_AudioProcessor::JK_AudioProcessor + 0x26 bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_filter.cpp (34): VCommanderVST.dll!createPluginFilter + 0x25 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_plugin_client\vst\juce_vst_wrapper.cpp (1454): VCommanderVST.dll!`anonymous namespace'::pluginEntryPoint + 0x5 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_plugin_client\vst\juce_vst_wrapper.cpp (1513): VCommanderVST.dll!VSTPluginMain + 0x9 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\format_types\juce_vstpluginformat.cpp (837): Plugin Host.exe!juce::VSTPluginInstance::VSTPluginInstance + 0x18 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\format_types\juce_vstpluginformat.cpp (2815): Plugin Host.exe!juce::VSTPluginFormat::createInstanceFromDescription + 0x26 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\format_types\juce_vstpluginformat.cpp (2732): Plugin Host.exe!juce::VSTPluginFormat::findAllTypesForFile + 0x1F bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_knownpluginlist.cpp (151): Plugin Host.exe!juce::KnownPluginList::scanAndAddFile
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_plugindirectoryscanner.cpp (85): Plugin Host.exe!juce::PluginDirectoryScanner::scanNextFile
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_pluginlistcomponent.cpp (273): Plugin Host.exe!juce::PluginListComponent::scanFor + 0xD bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_pluginlistcomponent.cpp (208): Plugin Host.exe!juce::PluginListComponent::timerCallback
    c:\eigene_dateien\vst_development\juce\modules\juce_events\timers\juce_timer.cpp (128): Plugin Host.exe!juce::Timer::TimerThread::callTimers
    c:\eigene_dateien\vst_development\juce\modules\juce_events\timers\juce_timer.cpp (197): Plugin Host.exe!juce::Timer::TimerThread::CallTimersMessage::messageCallback
    c:\eigene_dateien\vst_development\juce\modules\juce_events\native\juce_win32_messaging.cpp (50): Plugin Host.exe!juce::WindowsMessageHelpers::dispatchMessageFromLParam
    c:\eigene_dateien\vst_development\juce\modules\juce_events\native\juce_win32_messaging.cpp (111): Plugin Host.exe!juce::MessageManager::dispatchNextMessageOnSystemQueue + 0x9 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_events\messages\juce_messagemanager.cpp (120): Plugin Host.exe!juce::MessageManager::runDispatchLoopUntil + 0x10 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_events\messages\juce_messagemanager.cpp (101): Plugin Host.exe!juce::MessageManager::runDispatchLoop
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\application\juce_application.cpp (216): Plugin Host.exe!juce::JUCEApplication::main
    c:\eigene_dateien\vst_development\juce\extras\audio plugin host\source\hoststartup.cpp (110): Plugin Host.exe!WinMain + 0x18 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (275): Plugin Host.exe!__tmainCRTStartup + 0x2C bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (189): Plugin Host.exe!WinMainCRTStartup
    0x75E7339A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
    0x77909EF2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
    0x77909EC5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
  Data:
    40 83 1C 07    08 F1 1C 07    00 00 00 00    00 00 00 00     @....... ........
    10 00 00 00    01 00 00 00    94 07 00 00    FD FD FD FD     ........ ........
    60 A3 07 5E    01 00 00 00    00 00 00 00    00 DC 1C 07     `..^.... ........
    FD FD FD FD

…another one as this mainly appears!

---------- Block 2186 at 0x071D0228: 52 bytes ----------
  Call Stack:
    c:\eigene_dateien\vst_development\juce\modules\juce_events\broadcasters\juce_asyncupdater.cpp (51): VCommanderVST.dll!juce::AsyncUpdater::AsyncUpdater + 0x7 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_data_structures\values\juce_value.cpp (27): VCommanderVST.dll!juce::Value::ValueSource::ValueSource + 0x45 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_data_structures\values\juce_value.cpp (71): VCommanderVST.dll!juce::SimpleValueSource::SimpleValueSource + 0x33 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_data_structures\values\juce_value.cpp (109): VCommanderVST.dll!juce::Value::Value + 0x51 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_label.cpp (39): VCommanderVST.dll!juce::Label::Label + 0xDC bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\lookandfeel\juce_lookandfeel.cpp (1611): VCommanderVST.dll!juce::SliderLabelComp::SliderLabelComp + 0x1E bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\lookandfeel\juce_lookandfeel.cpp (1618): VCommanderVST.dll!juce::LookAndFeel::createSliderTextBox + 0x2E bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_slider.cpp (562): VCommanderVST.dll!juce::Slider::Pimpl::lookAndFeelChanged + 0x19 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_slider.cpp (1402): VCommanderVST.dll!juce::Slider::lookAndFeelChanged + 0x27 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\widgets\juce_slider.cpp (1401): VCommanderVST.dll!juce::Slider::colourChanged + 0x19 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\components\juce_component.cpp (2095): VCommanderVST.dll!juce::Component::setColour
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_methodsandclasses.cpp (2711): VCommanderVST.dll!JK_Slider::JK_Slider + 0x2B bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_vccontrols.cpp (281): VCommanderVST.dll!JK_VCControls::createControls + 0x52 bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_vccontrols.cpp (62): VCommanderVST.dll!JK_VCControls::JK_VCControls
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_methodsandclasses.cpp (52): VCommanderVST.dll!JK_ApplicationManager::JK_ApplicationManager + 0x2B bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_filter.cpp (43): VCommanderVST.dll!JK_AudioProcessor::JK_AudioProcessor + 0x26 bytes
    c:\eigene_dateien\vst_development\eigene projekte\vcommander\source\plugin\jk_filter.cpp (34): VCommanderVST.dll!createPluginFilter + 0x25 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_plugin_client\vst\juce_vst_wrapper.cpp (1454): VCommanderVST.dll!`anonymous namespace'::pluginEntryPoint + 0x5 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_plugin_client\vst\juce_vst_wrapper.cpp (1513): VCommanderVST.dll!VSTPluginMain + 0x9 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\format_types\juce_vstpluginformat.cpp (837): Plugin Host.exe!juce::VSTPluginInstance::VSTPluginInstance + 0x18 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\format_types\juce_vstpluginformat.cpp (2815): Plugin Host.exe!juce::VSTPluginFormat::createInstanceFromDescription + 0x26 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\format_types\juce_vstpluginformat.cpp (2732): Plugin Host.exe!juce::VSTPluginFormat::findAllTypesForFile + 0x1F bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_knownpluginlist.cpp (151): Plugin Host.exe!juce::KnownPluginList::scanAndAddFile
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_plugindirectoryscanner.cpp (85): Plugin Host.exe!juce::PluginDirectoryScanner::scanNextFile
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_pluginlistcomponent.cpp (273): Plugin Host.exe!juce::PluginListComponent::scanFor + 0xD bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_audio_processors\scanning\juce_pluginlistcomponent.cpp (208): Plugin Host.exe!juce::PluginListComponent::timerCallback
    c:\eigene_dateien\vst_development\juce\modules\juce_events\timers\juce_timer.cpp (128): Plugin Host.exe!juce::Timer::TimerThread::callTimers
    c:\eigene_dateien\vst_development\juce\modules\juce_events\timers\juce_timer.cpp (197): Plugin Host.exe!juce::Timer::TimerThread::CallTimersMessage::messageCallback
    c:\eigene_dateien\vst_development\juce\modules\juce_events\native\juce_win32_messaging.cpp (50): Plugin Host.exe!juce::WindowsMessageHelpers::dispatchMessageFromLParam
    c:\eigene_dateien\vst_development\juce\modules\juce_events\native\juce_win32_messaging.cpp (111): Plugin Host.exe!juce::MessageManager::dispatchNextMessageOnSystemQueue + 0x9 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_events\messages\juce_messagemanager.cpp (120): Plugin Host.exe!juce::MessageManager::runDispatchLoopUntil + 0x10 bytes
    c:\eigene_dateien\vst_development\juce\modules\juce_events\messages\juce_messagemanager.cpp (101): Plugin Host.exe!juce::MessageManager::runDispatchLoop
    c:\eigene_dateien\vst_development\juce\modules\juce_gui_basics\application\juce_application.cpp (216): Plugin Host.exe!juce::JUCEApplication::main
    c:\eigene_dateien\vst_development\juce\extras\audio plugin host\source\hoststartup.cpp (110): Plugin Host.exe!WinMain + 0x18 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (275): Plugin Host.exe!__tmainCRTStartup + 0x2C bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (189): Plugin Host.exe!WinMainCRTStartup
    0x75E7339A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
    0x77909EF2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
    0x77909EC5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
  Data:
    70 F6 1C 07    F0 02 1D 07    00 00 00 00    00 00 00 00     p....... ........
    10 00 00 00    01 00 00 00    8F 08 00 00    FD FD FD FD     ........ ........
    60 A3 07 5E    01 00 00 00    00 00 00 00    B0 F0 1C 07     `..^.... ........
    FD FD FD FD                                                  ........ ........

No, it does not, please be next time a little more precise! :evil: arrghh

[quote]e made the class where the OwnedArray with the controls lives derived from
Component and added the controls to it directly after creating.[/quote]
Why did you think this could change anything?. As a Plugin you are in special situation, when the gui isn’t open, the host may not triggering the plugins-message-thread, because he does only dsp-work. Seperate you dsp code from the gui-code, don’t make it depend from each other, its awful design.

This happens if you post something to the forum when you are away from the computer you are using to develop.
Sorry, took this from my mind and this seems to leak as well!
Does it mean this leak message has been generated by the built-in VC++ leak detector then?

Thank you for the explanation!
It should be easy to turn the UI controls into in the OwnedArray into property holder and use them when creating the UI controls when the editor is opened.

Thank you

Well, I have re- designed my class to not create UI controls w/o having the plugin editor opened.
This has removed almost all memory leaks but there are still some left and VLD pointed to:

  • Timer
  • ImageCache (ImageCache::Pimpl also uses a timer)

If I understood it right, a timer is also depend on message thread and same rules should apply. Is that true?
If yes, using these two classes w/o message thread would be a “no go”, right?

Thanks,

Damn right.

To be honest, unless you remove the juce_events module and all the other modules that depend on it, you can’t guarantee that some code somewhere won’t require the message thread and cause problems. But since you can’t build a plugin without using juce_events, then you’re really on your own with this one - I never designed it to work in an event-free situation.