Sharing HeapBlock variable across prepareToPlay() and processBlock()


#1

Hi all,

I'm using the lastest JUCE on OSX 10.9, and Xcode 5.1.1.

 

I have been having some trouble allocating a HeapBlock<float> in prepareToPlay() and accessing it in processBlock().

And the HeapBlock<float> variable is declared in the header file.

I have gone though other posts but they didn't work for me because whenever I try to access any element in the HeapBlock<float> variable I always get an error as below:


Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000001eab6000

 

This is what I'm doing:

1. After allocating the memory and inspect the memory address in prepareToPlay(), it looks like this:

    TempmemoryForBuffs.allocate(numChannels * 10, true);    

    char address[50];

    sprintf(address, "%p", (void*)TempmemoryForBuffs);

    String memoryAddress = String(address);  // --> This shows 0x1223f2000

 

2. If I inspect the same variable in processBlock(), it looks like this:

    char address[50];

    sprintf(address, "%p", (void*)TempmemoryForBuffs);

    String memoryAddress = String(address);  // --> This shows 0x223f2000

 

As you can see the memory address of the same variable in both places are different.

It seems to be that the memory address used in prepareToPlay() is using 64 bits, where as processBlock() is using 32 bits cutting off the upper 32 bits.

I am wondering how this could happen. Is this a problem with the JUCE version ?

Is it a case that processBlock() always uses 32 bit wide memory block somehow?

What could be a fix or workaround for situation like this?

 

Thank you,

 


#2

What’s the scoping of your heapblock?


#3

Thanks for your response.

The HeapBlock is a private variable in the Processor class.

 

In PluginProcessor.h ----------------------------------------------------------------------------

 

class StereoWidthCtrlAudioProcessor  : public AudioProcessor

{

public:

    StereoWidthCtrlAudioProcessor();

    ~StereoWidthCtrlAudioProcessor();

 

    void prepareToPlay (double sampleRate, int samplesPerBlock);

    void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);

 

private:

    HeapBlock <float> TempmemoryForBuffs;

}

 

In PluginProcessor.cpp ----------------------------------------------------------------------------

 

void StereoWidthCtrlAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)

{

    int numChannels     =   (int)getNumInputChannels();

   TempmemoryForBuffs.allocate(numChannels * 10, true);    

    char address[50];

    sprintf(address, "%p", (void*)TempmemoryForBuffs);

    String memoryAddress = String(address);  // --> This shows 0x1223f2000

}

 

void StereoWidthCtrlAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)

{

    char address[50];

    sprintf(address, "%p", (void*)TempmemoryForBuffs);

    String memoryAddress = String(address);  // --> This shows 0x223f2000

}


#4

Hi cpr,

Thank you very much for pointing that out.

Just to let other people who are having the same issue know, it turns out that the HeapBlock variable needs to be declared as either protected or public. Below code works:

 

In PluginProcessor.h ----------------------------------------------------------------------------

class StereoWidthCtrlAudioProcessor  : public AudioProcessor

{

public:

    StereoWidthCtrlAudioProcessor();

    ~StereoWidthCtrlAudioProcessor();

 

    void prepareToPlay (double sampleRate, int samplesPerBlock);

    void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);

 

protected:

    HeapBlock <float> TempmemoryForBuffs;

}

 

It's weird that with HeapBlock delared privately it works in VST3 but in the latest Logic Pro X.

It could be a bug in Logic.

 

Anyway, thank you so much.


#5

Just to let other people who are having the same issue know, it turns out that the HeapBlock variable needs to be declared as either protected or public. 

I really need to make it clear to you and anyone who reads this thread that this is the wrong conclusion!

Making a variable public or private makes absolutely no difference to the behaviour of anything in a program, it's purely a compile-time piece of information, it won't change the code that is generated at all. I don't know what you're doing elsewhere in your code that's messing up, but that is definitely not your problem! Nor is it a bug in logic. Perhaps some of your code is stamping over that memory address, and when you made it public you changed the order of the variables in your class, changing the memory layout and got lucky? Perhaps you're doing something else in your code that's breaking it. Impossible for us to tell from what you've said.

And be careful: writing (void*) TempBuffer is very dangerous. C-style casts are OK (but discouraged) for primitive types, but never use them on C++ class objects, always use static_cast so that you'll get a compiler error if you use it on a class that doesn't support that operator. sprintf is also a bad idea. A better way to write it would be:

DBG (String::toHexString ((int64) (pointer_sized_int) tempBuffer.getData()));

 


#6

Hi jules,

Thanks for pointing that out. It was my mistake to come to a conclusion blindly because I had had so much trouble with it for many days and it finally worked. So I suppose I  was so happy.

I moved the HeapBlock declaration at the top of private: section and it worked as well. It wasn't a bug in Logic or anything like that.

I knew that when a declared variable is used wrongfully anything declare under that can be affected.

I actually checked a few times that there is no funny thing going on in the declaration. There were only normal variables and fixed size arrays.

This is a shared project and I am not sure what's going on in the half of the project. So, I assumed it wouldn't have been a problem. 

Your post let us know that we have a bigger problem in the memory managment somewhere. Thanks. we will look into that.

 

As for the C style debugging, I am a great fan of C. So, I used a quick code just to check the memory address only to check what the problem was.

It wasn't a long term logging solution anyway :)

 

Thanks,