Thank you Benjamin, Jules and Joshua Gerrard for your answers.
I've removed code to isolate the issue. Sometimes the crash disappeared after I removed some code, but I had it popping up again when I added some more UI elements.
So the code I have now is only for testing, leaks memory badly, but - and that's the interesting part: The code is now only 200 lines, it's absolutely straightforward, but still crashes.
Here is the full thing to reproduce the crash (when built with Visual Studio Community 2015 on Windows 10, 32bit Release, static runtime, Optimisation set to "Maximise speed" and with Whole Program Optimisation set to "Enable link-time code generation when possible" in IntroJucer. No additional other flags. And also when using the latest version of JUCE from today.
Jules and Joshua Gerrard, can you have a look? I know it's a lot to ask for, but I would be very glad if you can. Also, because it is so straightforward, I wonder if it uncovers an incompatibility with these Visual Studio settings and JUCE.
Note that the code has a random looking combination of new menus and menu entries.. the problem is, removing single lines sometimes stops the crash, so I kept it this way.
CgMain.cpp:
#include "CgComponent.h"
int main(int argc, char* argv[])
{
std::cout << "START\n";
// Do a couple of loops, because the first one(s) might not crash yet.
for(int i = 0; i < 32; ++i)
{
std::cout << i << " ";
CgComponent component;
}
std::cout << "END\n";
return 0;
};
CgMenu.h:
#ifndef __CGMENU_H__
#define __CGMENU_H__
#include "JuceHeader.h"
class CgMenu: public juce::ComboBox
{
public:
CgMenu() { };
virtual ~CgMenu() { };
public:
void appendItem(const juce::String& newItemText)
{
addItem(newItemText, getNumItems() + 1);
};
};
#endif
CgComponent.h:
#ifndef __CGCOMPONENT_H__
#define __CGCOMPONENT_H__
#include "CgMenu.h"
class CgComponent: public juce::Component
{
public:
CgComponent()
{
{
CgMenu* menu = addMenu();
menu->appendItem("In From Host (VST Only)");
menu = addMenu();
menu->appendItem("All");
for(int i = 1; i <= 16; ++i)
menu->appendItem(juce::String(i));
menu = addMenu();
menu->appendItem("All Notes");
for(int i = 0; i < 9; ++i)
menu->appendItem("Octave " + juce::String(i));
for(int i = 0; i < 160; ++i)
{
menu = addMenu();
menu->appendItem("C");
menu->appendItem("C#");
menu->appendItem("D");
menu->appendItem("D#");
menu->appendItem("E");
menu->appendItem("F");
menu->appendItem("F#");
menu->appendItem("G");
menu->appendItem("G#");
menu->appendItem("A");
menu->appendItem("A#");
menu->appendItem("B");
}
}
{
CgMenu* menu = addMenu();
menu->appendItem("Out To Host (VST Only)");
menu = addMenu();
for(int i = 0; i < 16; ++i)
menu->appendItem(juce::String(i));
}
for(int i = 0; i < 16; ++i)
{
CgMenu* menu = addMenu();
menu->appendItem(juce::String(i));
}
{
CgMenu* const menu = addMenu();
menu->appendItem("Foo");
menu->appendItem("Foo");
menu->appendItem("Foo");
menu->appendItem("Foo");
menu->appendItem("Foo");
menu->appendItem("Foo");
menu->appendItem("Foo");
menu->appendItem("Foo");
for(int i = 0; i < 1000; ++i)
menu->appendItem(juce::String(i));
}
{
CgMenu* menu = addMenu();
menu->appendItem("Off");
for(int j = 0; j < 128; ++j)
menu->appendItem(juce::String(j));
}
for(int i = 0; i < 4; ++i)
{
CgMenu* menu = addMenu();
menu->appendItem("Beat Synced");
menu->appendItem("Beat Retrig.");
menu->appendItem("Beat 1-Shot");
menu->appendItem("Hertz Synced");
menu->appendItem("Hertz Retrig.");
menu->appendItem("Hertz 1-Shot");
menu->appendItem("Pitch -> Rate");
menu = addMenu();
menu->appendItem("1/128");
menu->appendItem("1/64");
menu->appendItem("1/32");
menu->appendItem("1/16");
menu->appendItem("1/8");
menu->appendItem("1/8d (3/16)");
menu->appendItem("1/4");
menu->appendItem("1/4d (3/8)");
menu->appendItem("1/2");
menu->appendItem("3/4");
menu->appendItem("1 Bar (4/4)");
menu->appendItem("1.5 Bars (6/4)");
menu->appendItem("2 Bars (8/4)");
menu->appendItem("3 Bars (12/4)");
menu->appendItem("4 Bars");
menu->appendItem("8 Bars");
menu->appendItem("16 Bars");
menu->appendItem("32 Bars");
menu = addMenu();
menu->appendItem("LFO Off");
for(int j = 0; j < 10; ++j)
menu->appendItem("Wave " + juce::String(j + 1));
menu->appendItem("Noise");
for(int j = 0; j < 1000; ++j)
menu->appendItem("Blo " + juce::String(i) + " -- " + juce::String(j));
}
for(int i = 0; i < 4; ++i)
{
CgMenu* menu = addMenu();
menu->appendItem("EG Off");
menu->appendItem("EG On");
for(int j = 0; j < 1000; ++j)
menu->appendItem("Bla " + juce::String(i) + " -- " + juce::String(j));
for(int j = 0; j < 1000; ++j)
menu->appendItem("Bla " + juce::String(i) + " -- " + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Gnar gnar" + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Blub blub" + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Mars" + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Mond" + juce::String(j));
for(int j = 0; j < 1000; ++j)
{
menu = addMenu();
menu->appendItem("Sterne" + juce::String(j));
menu->appendItem("Sterne" + juce::String(j));
}
}
for(int i = 0; i < 4; ++i)
{
CgMenu* menu = addMenu();
menu->appendItem("EG Off");
menu->appendItem("EG On");
for(int j = 0; j < 1000; ++j)
menu->appendItem("Bla " + juce::String(i) + " -- " + juce::String(j));
for(int j = 0; j < 1000; ++j)
menu->appendItem("Bla " + juce::String(i) + " -- " + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Gnar gnar" + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Blub blub" + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Mars" + juce::String(j));
menu = addMenu();
for(int j = 0; j < 1000; ++j)
menu->appendItem("Mond" + juce::String(j));
for(int j = 0; j < 1000; ++j)
{
menu = addMenu();
menu->appendItem("Sterne" + juce::String(j));
menu->appendItem("Sterne" + juce::String(j));
}
}
};
virtual ~CgComponent() { };
private:
CgMenu* addMenu(const juce::String& text = "")
{
return new CgMenu();
};
};
#endif
Juce's AppConfig.h:
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
There's a section below where you can add your own custom code safely, and the
Introjucer will preserve the contents of that block, but the best way to change
any of these definitions is by using the Introjucer's project settings.
Any commented-out settings will assume their default values.
*/
#ifndef __JUCE_APPCONFIG_FM0ZLV__
#define __JUCE_APPCONFIG_FM0ZLV__
//==============================================================================
// [BEGIN_USER_CODE_SECTION]
// (You can add your own code in this section, and the Introjucer will not overwrite it)
// [END_USER_CODE_SECTION]
//==============================================================================
#define JUCE_MODULE_AVAILABLE_juce_core 1
#define JUCE_MODULE_AVAILABLE_juce_data_structures 1
#define JUCE_MODULE_AVAILABLE_juce_events 1
#define JUCE_MODULE_AVAILABLE_juce_graphics 1
#define JUCE_MODULE_AVAILABLE_juce_gui_basics 1
//==============================================================================
#ifndef JUCE_STANDALONE_APPLICATION
#define JUCE_STANDALONE_APPLICATION 1
#endif
//==============================================================================
// juce_core flags:
#ifndef JUCE_FORCE_DEBUG
//#define JUCE_FORCE_DEBUG
#endif
#ifndef JUCE_LOG_ASSERTIONS
//#define JUCE_LOG_ASSERTIONS
#endif
#ifndef JUCE_CHECK_MEMORY_LEAKS
//#define JUCE_CHECK_MEMORY_LEAKS
#endif
#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
//#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
#endif
#ifndef JUCE_INCLUDE_ZLIB_CODE
//#define JUCE_INCLUDE_ZLIB_CODE
#endif
#ifndef JUCE_USE_CURL
//#define JUCE_USE_CURL
#endif
//==============================================================================
// juce_graphics flags:
#ifndef JUCE_USE_COREIMAGE_LOADER
//#define JUCE_USE_COREIMAGE_LOADER
#endif
#ifndef JUCE_USE_DIRECTWRITE
//#define JUCE_USE_DIRECTWRITE
#endif
//==============================================================================
// juce_gui_basics flags:
#ifndef JUCE_ENABLE_REPAINT_DEBUGGING
//#define JUCE_ENABLE_REPAINT_DEBUGGING
#endif
#ifndef JUCE_USE_XSHM
//#define JUCE_USE_XSHM
#endif
#ifndef JUCE_USE_XRENDER
//#define JUCE_USE_XRENDER
#endif
#ifndef JUCE_USE_XCURSOR
//#define JUCE_USE_XCURSOR
#endif
#endif // __JUCE_APPCONFIG_FM0ZLV__
The only thing which might be "special" is this (in CgComponent.h):
CgMenu* addMenu(const juce::String& text = "")
{
return new CgMenu();
};
That should not raise any issues, should it?
Thank you!