Hello,
This is in Juce 7.0.5.
I feel silly posting this because I’m sure it’s something obvious, but I’ve spent enough time already…
I’m trying to create a juce::StringArray
as well as two juce::Array<juce::Array<juce::StringArray>>
s to manage my parameter names since I got tired of making typos with them.
Here’s my declarations in the header:
private:
juce::StringArray tapParamNames;
juce::Array<juce::Array<juce::StringArray>> dampingParamNames;
juce::Array<juce::Array<juce::StringArray>> feedbackParamNames;
And the source:
//==============================================================================
// Populate database of reverb comb filter parameter names -KGK v1.6.3
void GlobeLoveler::initParamNames() {
DBG("Initializing parameter name strings");
/*
This throws a heap access violation: "**it** was 0xFFFFFFFFFFFFFFFF".
See first screenshot
*/
tapParamNames.ensureStorageAllocated(Constants::Reverb::filterCount);
for (int i = 0; i < Constants::Reverb::filterCount; ++i) {
juce::String tapParamName = GlobeRoomReverb::getTapParamName(i);
DBG(tapParamName);
DBG(String::formatted("tapParamNames.size (unsigned) = %d", tapParamNames.size()));
/*
Before adding `tapParamNames.ensureStorageAllocated(...), I got this far.
.add triggers a jassert, see second and third screenshots
*/
tapParamNames.add(tapParamName);
for (int c = 0; c < Constants::Reverb::numChannels; ++c) {
juce::StringArray newDampingParamNames;
juce::StringArray newFeedbackParamNames;
for (int r = 0; r < Constants::Reverb::roomCount; ++r) {
juce::String dampParamName = GlobeRoomReverb::getDampingParamName(c, i, r);
newDampingParamNames.add(dampParamName);
juce::String fdbkParamName = GlobeRoomReverb::getDampingParamName(c, i, r);
newFeedbackParamNames.add(fdbkParamName);
}
dampingParamNames[c][i].addArray(newDampingParamNames);
feedbackParamNames[c][i].addArray(newFeedbackParamNames);
}
}
}
And the methods which generate the strings:
Header:
public:
static juce::String getTapParamName(int i);
static juce::String getDampingParamName(int c, int i, int r);
static juce::String getFeedbackParamName(int c, int i, int r);
Source:
//==============================================================================
juce::String GlobeRoomReverb::getTapParamName(int i)
{
return String::formatted("reverb.comb[0,1][%i].tap", i);
}
//==============================================================================
juce::String GlobeRoomReverb::getDampingParamName(int c, int i, int r)
{
return String::formatted("reverb.comb[%i][%i].damping[%i]", c, i, r);
}
//==============================================================================
juce::String GlobeRoomReverb::getFeedbackParamName(int c, int i, int r)
{
return String::formatted("reverb.comb[%i][%i].feedback[%i]", c, i, r);
}
Here’s the heap access error when I run that code:
(from
debug_heap.cpp
)(what’s up with the weird characters in value??)
Full call stack:
> ucrtbased.dll!check_bytes(const unsigned char * const first, const unsigned char value, const unsigned __int64 size) Line 194 C++
ucrtbased.dll!is_block_an_aligned_allocation(const void * const block) Line 252 C++
ucrtbased.dll!free_dbg_nolock(void * const block, const int block_use) Line 886 C++
ucrtbased.dll!_free_dbg(void * block, int block_use) Line 1030 C++
ucrtbased.dll!free(void * block) Line 32 C++
GlobeLoveler.exe!juce::HeapBlock<juce::String,0>::~HeapBlock<juce::String,0>() Line 137 C++
GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::setAllocatedSizeInternal(int numElements) Line 431 C++
GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::setAllocatedSize(int numElements) Line 217 C++
GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::ensureAllocatedSize(int minNumElements) Line 230 C++
GlobeLoveler.exe!juce::Array<juce::String,juce::DummyCriticalSection,0>::ensureStorageAllocated(int minNumElements) Line 1044 C++
GlobeLoveler.exe!juce::StringArray::ensureStorageAllocated(int minNumElements) Line 467 C++
GlobeLoveler.exe!GlobeLoveler::initParamNames() Line 729 C++
Here’s the debugging output with .ensureStorageAllocated(...)
commented out:
Initializing strings
reverb.comb[0,1][0].tap
tapParamNames.size (unsigned) = -842150451
The parameter name is as I expect (side note: is it bad practice to use brackets, periods, etc. in parameter names?). But the size is obviously wrong.
Here are screenshots of the jassert and its arguments:
(from juce_ArrayBase.h
)
And the full call stack:
> GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::setAllocatedSize(int numElements) Line 212 C++
GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::ensureAllocatedSize(int minNumElements) Line 230 C++
GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::addImpl<juce::String>(juce::String && <toAdd_0>) Line 547 C++
GlobeLoveler.exe!juce::ArrayBase<juce::String,juce::DummyCriticalSection>::add(juce::String && newElement) Line 264 C++
GlobeLoveler.exe!juce::Array<juce::String,juce::DummyCriticalSection,0>::add(juce::String && newElement) Line 432 C++
GlobeLoveler.exe!juce::StringArray::add(juce::String newString) Line 140 C++
GlobeLoveler.exe!GlobeLoveler::initParamNames() Line 735 C++
So, why is the array initialized to a negative size? Why am I seeing negative numElements and numUsed when I try to add a string?
I also tried to initialize the array like so: tapParamNames = juce::StringArray();
even though I’ve read this is unnecessary in multiple posts. It causes the same issue as in case #1 (calling .ensureStorageAllocated
→ heap error).
I also returned a generic string in the getTapParamName
method, to see if the problem was with String::formatted()
, but this did not affect the behavior.
I thought it was probably a pointer/reference error for a while, but since I couldn’t even set the size on the array before adding objects, I’m thinking it’s deeper than that now.
Thanks for reading.