I think this is probably a really simple question, but I am as much a C++ developer as the guys at the walmart meat counter are butchers.
Say I have:
class Parent{
protected:
~Parent(){};
};
class ChildA : public Parent{
};
struct Container{
Parent *child;
//Tried this, causes: munmap_chunk(): invalid pointer
~Container(){
delete &child;
}
};
Container MakeStruct(){
ChildA child = *new ChildA();
return Container { .child = &child };
}
int main()
{
Container cont = MakeStruct();
//Tried this, causes: "Parent::~Parent()" is inaccessible
delete cont.child;
}
As you can see, I am using new to create a ChildA because I need it to outlive the MakeStruct function. So I know this means that child (in MakeStruct) will be placed on the heap, and that I am responsible for deleting it. But I can't seem to delete it.
I can't change the type of child in Container because I need it to accept both a ChildA and a ChildB. It sort of makes sense, considering the destructor of Parent is protected. I have no control over Parent or either Child. They are part of an external library.
I case it helps, the actual code I'm working with is a library called ArduinoJson.
I am trying to return either a DynamicJsonDocument or a StaticJsonDocument<T> from a function, wrapped in a struct taking a JsonDocument:
Here is the struct that contains the JsonDocument:
struct rpc_handler_result_t {
esp_err_t result;
JsonDocument *response;
};
which is returned from:
{
const int len = JSON_OBJECT_SIZE(1);
StaticJsonDocument<len> reply = *new StaticJsonDocument<len>;
reply["MaxOutput"] = Configuration::GetMaxOutputAmps();
rpc_handler_result_t res = {
.result = ESP_OK,
.response = reply
};
return res;
}
When you eventually call
delete, you must pass it precisely the value you got fromnew. So you must store the value thatnewreturns somewhere. But look at your call tonew-- it dereferences that value and never stores it anywhere. So how can you calldelete?!This is all wrong. You create a new object by calling
new. But you do not store the valuenewreturned anywhere. Now,childis a temporary object whose value was copy-constructed from the value of the object you allocated withnewand leaked.Then, you save the address of the temporary
childobject you created on the stack. But that object won't exist after youreturn.What you wanted to do was save the value that
newreturned. But you got rid of it immediately by dereferencing it and never saving it.So:
newreturns so you candeleteit later.You wanted
.child = new ChildA(), setting thechildmember to be a pointer to the object created bynew, not a pointer to some temporary, local object. You can save the valuenewreturns in a temporary if you want, just make sure.childgets the valuenewreturned and not any other value.Also:
This is wrong too. What type is
&child? Is&childsomething you got fromnew? This should bedelete child;.