通过使用具有受保护的析构函数的父类型实例化基 class 创建的可用内存

Free memory created by instantiating base class with parent type that has protected destructor

我认为这可能是一个非常简单的问题,但我是一名 C++ 开发人员,就像沃尔玛肉类柜台的屠夫一样。

假设我有:

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;
}

如您所见,我正在使用 new 创建一个 ChildA,因为我需要它比 MakeStruct 函数更有效。所以我知道这意味着 child(在 MakeStruct 中)将被放在堆上,我负责删除它。但我似乎无法删除它。 我无法更改 Containerchild 的类型,因为我需要它接受 ChildAChildB。考虑到 Parent 的析构函数受到保护,这是有道理的。我无法控制 ParentChild。它们是外部库的一部分。

如果有帮助,我正在使用的实际代码是一个名为 ArduinoJson 的库。

我正在尝试 return 来自函数的 DynamicJsonDocumentStaticJsonDocument<T>,包装在采用 JsonDocument:

的结构中

这是包含 JsonDocument:

的结构
struct rpc_handler_result_t {
    esp_err_t result;
    JsonDocument *response;
};

return编辑自:

{
    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;
}

当您最终调用 delete 时,您必须准确地将您从 new 获得的值传递给它。因此,您必须new returns 的值存储在某处。但是看看您对 new 的调用——它取消引用该值并且 never 将它存储在任何地方。那么如何调用 delete?!

 Container MakeStruct(){
    ChildA child = *new ChildA(); // The value returned by new is lost here
    return Container { .child = &child }; // child is a local object here
}

这都是错误的。您通过调用 new 创建一个新对象。但是您不会将返回的值 new 存储在任何地方。现在,child 是一个临时对象,其值是根据您使用 new 分配并泄漏的对象的值复制构造的。

然后,您将创建的临时 child 对象的地址保存在堆栈中。但是在 return.

之后该对象将不存在

您想要做的是保存 new 返回的 。但是您通过取消引用它并且从不保存它而立即摆脱了它。

所以:

  1. 必须 存储 new returns 的值,以便您以后可以 delete 它。
  2. 不要尝试将本地对象的地址传递到函数之外。

您想要 .child = new ChildA(),将 child 成员设置为指向由 new 创建的对象的指针,而不是指向某个临时本地对象的指针。如果需要,您可以临时保存值 new returns,只需确保 .child 获得返回的值 new 而不是任何其他值。

还有:

Parent *child;

//Tried this, causes: munmap_chunk(): invalid pointer
~Container(){
    delete &child;
}

这也是错误的。 &child 是什么类型? &child 是你从 new 那里得到的东西吗?这应该是 delete child;.