Inheriting an OwnedArray

I am having an issue with the deletion of objects within OwnedArrays, and would appreciate some help.
I have a static library that contains the OwnedArrays, and a test program that uses the library.

My program works fine, but I get an exception thrown caused by “Access violation reading location 0xFFFFFFFFFFFFFFFF” when the program ends. It is a debug build under Windows.

The above access violation message appears right after the following:

 static void destroy (ObjectType* object)
    {
        // If the line below triggers a compiler error, it means that you are using
        // an incomplete type for ObjectType (for example, a type that is declared
        // but not defined). This is a problem because then the following delete is
        // undefined behaviour. The purpose of the sizeof is to capture this situation.
        // If this was caused by a OwnedArray of a forward-declared type, move the
        // implementation of all methods trying to use the OwnedArray (e.g. the destructor
        // of the class owning it) into cpp files where they can see to the definition
        // of ObjectType. This should fix the error.
        ignoreUnused (sizeof (ObjectType));

        delete object;

I have an OwnedArray of Speaker in the SpeakerConfig class:

#include "JuceHeader.h"
#include <Eigen\Dense>
#include "Speaker.h"

class SpeakerConfig
{
public:
	float verticalTolerance = 50;
	juce::OwnedArray<Speaker> speakers;				//array of pointers to the speakers

The classes Zone and Layer inherit from SpeakerConfig and use the speakers array. Zone has an OwnedArray of Layer:

class Zone : public SpeakerConfig
{
public:
	juce::String Name;
	float covariance;			//the covariance of speakers in this zone
	juce::OwnedArray<Layer> layers;	//array of pointers to Layers

There are algorithms in a SoundSource class that will utilize speaker positions and will access the speakers via a pointer to the appropriate Zone or Layer within a Zone:

void SoundSource::renderVBAP(SpeakerConfig* speakerConfigPtr, float x, float y, float z, float spread) {

I have followed the error message recommendations and ensured that there is a destructor for the Speaker and Layer classes in the cpp files. Both classes are defined in header files included above where they are used in OwnedArray declarations.

I’m wondering whether my use of an inherited array is somehow causing the problem?

The text at the assert talks of a compiler error. Since you face a runtime error, this is a red herring.

I would guess it is a double delete. This can happen if an object is owned at different places, like adding it twice to an OwnedArray or to different OwnedArrays.
Another mistake is putting an object from the stack to an OwnedArray.

Enabling the Address Sanitizer might give additional clues.

But I think the mistake is in the parts you didn’t post.

That’s very helpful, thank you Daniel!!

The same speaker objects are appearing in OwnedArrays declared within the Zone and Layer classes. This makes sense as a model of the configuration. Now how to fix the implementation so that the double delete doesn’t happen!

An OwnedArray is a container intended to own something. Owning the same object instance two times is wrong on a conceptual basis, so OwnedArray is obviously the wrong container choice here.

If an object should be shared by multiple owners, a usual pattern is to use a std::shared_ptr which can be easily put into a vector like std::vector<std::shared_ptr<Speaker>>. The shared pointer tracks how many references to the speaker are there and will only destruct the instance when the reference count goes to 0.

Thank you SO much for this clear instructive message!!

The vector of shared pointers is indeed the right container choice and has worked perfectly!

Very grateful!!