删除c++中的void*指针

Delete void* pointer in c++

本文关键字:指针 void 中的 c++ 删除      更新时间:2023-10-16

我正在阅读c++思维,第13章:动态对象创建。在本章中,Eckel谈到删除void*可能是一个bug。下面的段落把我弄糊涂了。

另一个内存泄漏问题与确保删除是有关的实际调用容器中保存的每个对象指针。的容器不能"拥有"指针,因为它将指针保存为void* and类型因此不能执行适当的清理。用户必须对此负责用于清理物体。这就产生了一个严重的问题添加指针指向在堆栈上创建的对象和在堆栈上创建的对象因为delete表达式不安全,所以将堆放到同一个容器中对于尚未在堆上分配的指针。

谁能更详细地解释为什么"将指向堆栈上创建的对象的指针和在堆上创建的对象添加到同一容器"会产生严重的问题?

为了使问题更清楚,我添加了相关的代码片段。

class Stack {
  struct Link {
    void* data;
    Link* next;
    void initialize(void* dat, Link* nxt);
  }* head;
public:
  void initialize();
  void push(void* dat);
  void* peek();
  void* pop();
  void cleanup();
};

作为一般规则,堆栈上的对象不需要删除,堆上的对象需要删除。如果您将它们放在同一个容器中,您如何跟踪要删除哪些?最好有两个容器,一个用于堆栈上的对象(不需要删除的对象),另一个用于堆上的对象(需要删除的对象)。

这段话确实有点模糊。在我看来,它混合了两个不同的问题,这导致了混乱。

  1. 为了正确删除对象,编译器必须知道对象的类型。对于void*,类型是未知的(这正是使用void*的目的——隐藏实际类型)。因此,如果不转换为正确的实际类型,就不能在这样的对象上执行删除。
  2. 通常使用void*意味着指向对象的所有权属于某个外部实体,而不是包含指针的实体。在实体内部,指针是不透明的,充当外部对象的处理程序,就实体而言,它是一个黑盒。Stack类必须很好地意识到责任划分,并且不能试图销毁void*对象,因为它既不知道它的生命周期(例如,导致试图释放堆栈变量),也不知道应该在销毁时执行的操作(导致功能不正确)。