1

我正在阅读 C++ 中的思考,第 13 章:动态对象创建。在本章中,Eckel 谈到删除 void* 可能是一个 bug。以下段落让我感到困惑。

另一个内存泄漏问题与确保为容器中保存的每个对象指针实际调用删除有关。容器不能“拥有”指针,因为它将指针作为 void* 保存,因此无法执行正确的清理。用户必须负责清理对象。如果将指向在堆栈上创建的对象和在堆上创建的对象的指针添加到同一个容器,这会产生一个严重的问题,因为删除表达式对于尚未在堆上分配的指针是不安全的。

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

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

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();
};
4

2 回答 2

2

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

于 2013-04-08T16:32:04.980 回答
1

This paragraph is indeed a bit vague. It mixes 2 different issues and that leads to confusion, in my opinion.

  1. In order to correctly delete an object, its type must be known to the compiler. For void* the type isn't known (that's exactly the point of using void* - to hide the actual type). So the deletion can't be performed on such object without casting to the proper actual type.
  2. Normally usage of void* implies that ownership of the pointed object belongs to some outer entity by design, and not to the entity containing the pointer. Inside the entity the pointer is opaque and serves as a handler to an external object, which is a black-box as far as the the entity is concerned. The Stack class must be well aware of the responsibilities division and must not attempt to destroy the void* object since it has no idea neither about it's lifetime (leading to attempt to free stack variable, for example), nor about the operations that should be done upon the destruction (leading to functional incorrectness).
于 2013-04-08T16:41:49.423 回答