1

C++ での思考、第 13 章: 動的オブジェクトの作成を読んでいます。この章で、void* の削除に関する Eckel の話は、おそらくバグである可能性があります。次の段落は私を混乱させます。

もう 1 つのメモリ リークの問題は、コンテナーに保持されている各オブジェクト ポインターに対して実際に delete が呼び出されるようにすることです。コンテナーはポインターを 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

原則として、スタック上のオブジェクトは削除する必要がなく、ヒープ上のオブジェクトは削除する必要があります。それらを同じコンテナーに配置した場合、どのコンテナーを削除するかをどのように追跡しますか? 1 つはスタック上のオブジェクト (削除する必要がないもの) 用で、もう 1 つはヒープ上のオブジェクト (削除する必要があるもの) 用です。

于 2013-04-08T16:32:04.980 に答える
1

この段落は確かに少しあいまいです。私の意見では、2 つの異なる問題が混在しているため、混乱が生じます。

  1. オブジェクトを正しく削除するには、その型がコンパイラに認識されている必要があります。void*タイプが不明なためです(void*実際のタイプを非表示にするために使用するのはまさにそれです)。したがって、適切な実際の型にキャストしない限り、そのようなオブジェクトに対して削除を実行することはできません。
  2. 通常、 の使用は、指定されたオブジェクトの所有権が、ポインターを含むエンティティではなく、設計によりvoid*何らかの外部エンティティに属することを意味します。エンティティの内部では、ポインタは不透明であり、エンティティに関する限りブラックボックスである外部オブジェクトへのハンドラとして機能します。クラスは責任分割を十分に認識している必要があり、オブジェクトの有効期間 (たとえば、スタック変数を解放しようとすることにつながる) もオブジェクトに対して実行する必要がある操作も知らないため、オブジェクトを破棄しようとしてはなりません。破壊(機能の誤りにつながる)。Stackvoid*
于 2013-04-08T16:41:49.423 に答える