Search code examples
c++windowsdllcmakejuce

crash in Windows dll plugin on load


Looking for some advice as to what can cause a crash of this type in Windows when loading a dll.

enter image description here

I'm writing a Windows VST3 .dll plugin in C++, and experiencing a crash on startup when my .dll is loaded. When running the host application and the plugin via Visual Studio 2019 debugger I'm getting the Access violation executing location ... dialog shown above, and the call stack is empty, making me think memory is completely corrupted.

Maybe this is caused by linking options I need to tweak when building the .dll?

Here are some facts:

  • The plugin itself works fine. I can get it to load and unload without issues when all 3rd party API calls are commented out.
  • If I link some 3rd party libraries into my plugin, then again everything works fine.
  • Once I make a call to any of those 3rd party libraries, then that causes the segfault on startup.
  • Plugin is built with /MD, but I also tried /MT and saw the same behaviour.
  • I'm using JUCE C++ to get the VST3 framework and GUI components.
  • An example of one of the 3rd party library I'm linking against and attempting to call into is the SuperpoweredSDK C++ library. But I've tried other libraries, and I'm seeing the same behaviour with each one.

Unfortunately, getting an entire blank VST3 plugin together is too much code to post in a StackOverflow question. But since I can get the plugin to work if I comment out all calls to 3rd party libraries, I don't think the code itself is the issue, I think the way the dll (.vst3) file is built is the problem.

The critical portion of the CMakeLists.txt file that builds the .vst3 dll file looks like this:

FIND_LIBRARY ( SuperpoweredSDK NAMES SuperpoweredWin141_Debug_MD_x64.lib PATHS ${SUPERPOWERED_DIR}/libWindows )
SET ( TEST_EXTERNAL_DEPS PRIVATE Threads::Threads ${SuperpoweredSDK} )

FILE ( GLOB JUCE_SOURCE ${CMAKE_HOME_DIRECTORY}/JuceLibraryCode/*.cpp )
LIST ( FILTER JUCE_SOURCE EXCLUDE REGEX ".+/JuceLibraryCode/include_juce_audio_plugin_client_[^u].+" )

FILE ( GLOB PLUGIN_SOURCE *.cpp )

ADD_LIBRARY ( TestVST3 SHARED ${JUCE_SOURCE} ${PLUGIN_SOURCE} ${CMAKE_HOME_DIRECTORY}/JuceLibraryCode/include_juce_audio_plugin_client_VST3.cpp )
SET_TARGET_PROPERTIES ( TestVST3 PROPERTIES OUTPUT_NAME "Test" SUFFIX ".vst3" )
TARGET_LINK_LIBRARIES ( TestVST3 PUBLIC ${TEST_EXTERNAL_DEPS} )

Solution

  • We eventually did find the cause of this crash. With VST3 files, the DAW loads each .dll (or .vst3), queries the capabilities, and immediately unloads the dll again. It then moves on to the next file, and the process starts all over until all plugins have been queried.

    In this case, one of the 3rd party libs I was using (SuperpoweredSDK) starts a background thread to verify the license against a web server somewhere. This was not documented. With the background thread started, the DAW unknowingly proceeds to unload the DLL, leaving the thread hanging there running code that no longer exists! And thus, the crash without any call stack.

    Several possible solutions:

    • Move the SuperpoweredSDK initialization code until later when it really is needed.
    • In a future not-yet-released version of SuperpoweredSDK (current version is 2.0.1), they're apparently adding an API call to shutdown Superpowered, and that shutdown call will wait until all background threads have finished running. Make sure you call this new API.