Crash with #include "AppConfig.h" + JUCE_CHECK_MEMORY_LEAKS


#1

When this line in juce_AudioDeviceManager.cpp executes:

AudioDeviceManager::setAudioDeviceSetup()

currentSetup = newSetup;

I get a corrupted heap when the BigIntegers get assigned. I’m guessing this might have something to do with JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS? I’m running Visual Studio 2010. When I switch to “Multithreaded Debug” (to use the CRT debug heap) the problem disappears. The problem does not exist in my debug build. In an effort to narrow this problem down I have turned off optimizations in my Release build, and I still get the problem.

I’ve been trying to track this down for days now and I’m having no luck whatsoever. It happened when I moved to the modules branch. Any ideas?

UPDATED POST TITLE to reflect new information.


#2

I tried defining JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS to 0 instead of 1 in the appropriate Juce header and it didn’t resolve the issue.


#3

I just updated to tip and rebuilt a few things and don’t see the problem here (VC2010, 32 and 64 bit builds). Can you point to a simple case that has the problem?


#4

I cannot. I’ve been trying to track it down for many hours to no avail. It only happens with the non-debug C Runtime. I turned off optimizations and it still happens. AudioDeviceManager::currentSetup constructs normally but when the constructor returns the inputDeviceName and outputDeviceName get invalid pointers. I will spend more time tomorrow.


#5

Can’t see any obvious mistakes in there… And if there were, I’d expect things like the cryptography classes to explode, since they make heavy use of BigInteger shuffling.

Those “corrupted heap” messages normally pop up on the next allocator call AFTER the memory gets corrupted, so maybe the real culprit is something that happened just before the BigInteger copy?


#6

I had one of those Friday and Saturday. Not fun. Sorry!


#7

[quote=“jfitzpat”][quote=“TheVinn”]
I’ve been trying to track it down for many hours to no avail.
[/quote]

I had one of those Friday and Saturday. Not fun. Sorry![/quote]

I’m in the middle of one myself, involving random crashes in Android and no way to get a stack trace out of the damn thing. :x


#8

Just a guess but I think it might have something to do with statically linking with boost and a mismatch in the CRT debug heap versus the normal heap…


#9

Okay after a lot of work I have managed to comment out everything except the user interface in my application. So no AudioDeviceManager, etc… and I still get a heap corruption bringing up a mostly empty window with a simple menubar. This is what I know so far:

  • Heap gets corrupted when running the non-debug C Runtime

  • Happens with optimizations turned off or on in the build

  • Doesn’t happen if I don’t bring up the main window

  • Happens even when all audio / application logic is turned off

  • Does not happen with the debug C Runtime


#10

I have boiled it down to this simple app:

// Copyright (C) 2008 by One Guy Group, Inc., All rights reserved worldwide.

#include "modules/juce_core/juce_core.h"
#include "modules/juce_gui_basics/juce_gui_basics.h"
#include "modules/juce_data_structures/juce_data_structures.h"
#include "modules/juce_events/juce_events.h"
#include "modules/juce_graphics/juce_graphics.h"
#include "modules/juce_video/juce_video.h"
#include "modules/juce_opengl/juce_opengl.h"
#include "modules/juce_audio_basics/juce_audio_basics.h"
#include "modules/juce_audio_formats/juce_audio_formats.h"
#include "modules/juce_audio_processors/juce_audio_processors.h"
#include "modules/juce_audio_devices/juce_audio_devices.h"
#include "modules/juce_cryptography/juce_cryptography.h"
#include "modules/juce_gui_extra/juce_gui_extra.h"
#include "modules/juce_audio_utils/juce_audio_utils.h"

using namespace juce;

#include "MainApp.h"

static const String APPNAME("CrashTestDummy");
static const String APPVERSION("1.0.0 Pre-release");
static const String OKTEXT("OK");

MainApp* MainApp::s_app = 0;

MainApp::MainApp()
{
  jassert( !s_app );

  s_app = this;

  // NEVER do anything in here that could involve any Juce function being called
  // - leave all your startup tasks until the initialise() method.
}

MainApp::~MainApp()
{
  // Your shutdown() method should already have done all the things necessary to
  // clean up this app object, so you should never need to put anything in
  // the destructor.

  // Making any Juce calls in here could be very dangerous...

  s_app = 0;
}

void MainApp::initialise (String const&)
{
  bool shouldRun = true;

  if (shouldRun)
  {
    JUCE_TRY
    {
	  Component* w = new DocumentWindow (
		"Crash Test",
		Colours::azure,
		DocumentWindow::allButtons,
		true);

	  w->setVisible (true);
    }
    JUCE_CATCH_EXCEPTION
  }

  if (!shouldRun)
  {
    JUCEApplication::quit();
  }
}

void MainApp::shutdown()
{
}

const String MainApp::getApplicationName()
{
    return APPNAME;
}

const String MainApp::getApplicationVersion()
{
    return APPVERSION;
}

bool MainApp::moreThanOneInstanceAllowed()
{
  // Have to allow multiples so we can show bullet-proof
  // alert windows via launching a second process.
  return true;
}

void MainApp::anotherInstanceStarted (const String& commandLine)
{
}

START_JUCE_APPLICATION (MainApp)

I sent it to a friend of mine and when he builds it and runs, it doesn’t corrupt. Still searching.


#11

I’ll try to build it in a bit.


#12

Not necessary…I’m tracking it down. Besides, if you build it, it won’t corrupt. It seems my machine is producing executables that are different from everyone else…no joke. I’m doing some md5/SHA testing now. I’m guessing that my SSD has a failed sector somewhere.


#13

Okay this is what I have so far:

AppConfig.h

/*

    IMPORTANT! This file is auto-generated each time you save your
    project - if you alter its contents, your changes may be overwritten!

    If you want to change any of these values, use the Introjucer to do so,
    rather than editing this file directly!

    Any commented-out settings will assume their default values.

*/

#ifndef __JUCE_APPCONFIG_IVABE4__
#define __JUCE_APPCONFIG_IVABE4__

#define JUCE_CHECK_MEMORY_LEAKS 1

//==============================================================================
// VF: These seem to be unused
#define JUCE_MODULE_AVAILABLE_juce_audio_basics          1
#define JUCE_MODULE_AVAILABLE_juce_audio_devices         1
#define JUCE_MODULE_AVAILABLE_juce_audio_formats         1
#define JUCE_MODULE_AVAILABLE_juce_audio_processors      1
#define JUCE_MODULE_AVAILABLE_juce_core                  1
#define JUCE_MODULE_AVAILABLE_juce_cryptography          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
#define JUCE_MODULE_AVAILABLE_juce_gui_extra             1
#define JUCE_MODULE_AVAILABLE_juce_opengl                1
#define JUCE_MODULE_AVAILABLE_juce_video                 1

//==============================================================================
// juce_audio_devices flags:

#ifndef JUCE_ASIO
#define JUCE_ASIO 1
#endif

#ifndef JUCE_WASAPI
#define JUCE_WASAPI 1
#endif

#ifndef JUCE_DIRECTSOUND
#define JUCE_DIRECTSOUND 1
#endif

#ifndef JUCE_ALSA
#define JUCE_ALSA 1
#endif

#ifndef JUCE_JACK
#define JUCE_JACK 1
#endif

#ifndef JUCE_USE_CDREADER
 //#define JUCE_USE_CDREADER
#endif

#ifndef    JUCE_USE_CDBURNER
 //#define JUCE_USE_CDBURNER
#endif

//==============================================================================
// juce_audio_formats flags:

#ifndef JUCE_USE_FLAC
#define JUCE_USE_FLAC 1
#endif

#ifndef JUCE_USE_OGGVORBIS
#define JUCE_USE_OGGVORBIS 1
#endif

#ifndef JUCE_USE_MP3AUDIOFORMAT
#define JUCE_USE_MP3AUDIOFORMAT 0
#endif

//==============================================================================
// juce_audio_processors flags:

#ifndef JUCE_PLUGINHOST_VST
#define JUCE_PLUGINHOST_VST 1
#endif

#ifndef JUCE_PLUGINHOST_AU
#define JUCE_PLUGINHOST_AU 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 1
#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

//==============================================================================
// juce_gui_extra flags:

#ifndef    JUCE_WEB_BROWSER
 //#define JUCE_WEB_BROWSER
#endif

//==============================================================================
// juce_video flags:

#ifndef    JUCE_DIRECTSHOW
 //#define JUCE_DIRECTSHOW
#endif

#ifndef    JUCE_MEDIAFOUNDATION
 //#define JUCE_MEDIAFOUNDATION
#endif

#ifndef    JUCE_QUICKTIME
 //#define JUCE_QUICKTIME
#endif

#ifndef    JUCE_USE_CAMERA
 //#define JUCE_USE_CAMERA
#endif

#endif

MainApp.cpp

// Copyright (C) 2008 by One Guy Group, Inc., All rights reserved worldwide.

// Un-comment to fix crash
//#include "AppConfig.h"

#include "modules/juce_core/juce_core.h"
#include "modules/juce_gui_basics/juce_gui_basics.h"
#include "modules/juce_data_structures/juce_data_structures.h"
#include "modules/juce_events/juce_events.h"
#include "modules/juce_graphics/juce_graphics.h"
#include "modules/juce_video/juce_video.h"
#include "modules/juce_opengl/juce_opengl.h"
#include "modules/juce_audio_basics/juce_audio_basics.h"
#include "modules/juce_audio_formats/juce_audio_formats.h"
#include "modules/juce_audio_processors/juce_audio_processors.h"
#include "modules/juce_audio_devices/juce_audio_devices.h"
#include "modules/juce_cryptography/juce_cryptography.h"
#include "modules/juce_gui_extra/juce_gui_extra.h"
#include "modules/juce_audio_utils/juce_audio_utils.h"

using namespace juce;

#include "MainApp.h"

static const String APPNAME("CrashTestDummy");
static const String APPVERSION("1.0.0 Pre-release");
static const String OKTEXT("OK");

class MainWindow : public DocumentWindow
{
public:
  MainWindow () : DocumentWindow (
	"Crash Test",
	Colours::azure,
	DocumentWindow::allButtons,
	true
	)
  {
  }

  void closeButtonPressed ()
  {
	JUCEApplication::getInstance()->systemRequestedQuit();
	delete this;
  }
};

MainApp* MainApp::s_app = 0;

MainApp::MainApp()
{
  jassert( !s_app );

  s_app = this;

  // NEVER do anything in here that could involve any Juce function being called
  // - leave all your startup tasks until the initialise() method.
}

MainApp::~MainApp()
{
  // Your shutdown() method should already have done all the things necessary to
  // clean up this app object, so you should never need to put anything in
  // the destructor.

  // Making any Juce calls in here could be very dangerous...

  s_app = 0;
}

void MainApp::initialise (String const&)
{
  bool shouldRun = true;

  if (shouldRun)
  {
    JUCE_TRY
    {
	  Component* w = new MainWindow;

	  w->setVisible (true);
    }
    JUCE_CATCH_EXCEPTION
  }

  if (!shouldRun)
  {
    JUCEApplication::quit();
  }
}

void MainApp::shutdown()
{
}

const String MainApp::getApplicationName()
{
    return APPNAME;
}

const String MainApp::getApplicationVersion()
{
    return APPVERSION;
}

bool MainApp::moreThanOneInstanceAllowed()
{
  // Have to allow multiples so we can show bullet-proof
  // alert windows via launching a second process.
  return true;
}

void MainApp::anotherInstanceStarted (const String& commandLine)
{
}

START_JUCE_APPLICATION (MainApp)

This application corrupts the heap in Release (but not in Debug). Uncommenting the #include “AppConfig.h” from MainApp.cpp makes the problem go away.

Also, deleting everything in AppConfig.h makes the problem go away as well.


#14

Alright this is the problem.

AppConfig.h

...
#define JUCE_CHECK_MEMORY_LEAKS 1
...

SourceFile.cpp

#include "AppConfig.h"
#include "modules/juce_core/juce_core.h"

If AppConfig.h defines JUCE_CHECK_MEMORY_LEAKS to 1 but AppConfig.h is not included in source files that include Juce module headers, it causes corrupted heaps when running with the non-debug C Runtime. This was a pain in the ass to track down.


#15

Ouch! I’be been bit by that type of thing before, ie. conditional compilation in header file, condition setting different in different source files which include said header… :frowning:


#16

Yes, that sort of thing is a bugger to track down.

I hit something similar a few years ago, and tried to figure out a way to cause some kind of compile error if you mis-link it, but couldn’t come up with a decent solution.


#17

I think juce_core.h should include AppConfig.h to prevent this, or similar problems, from ever happening