1. ホーム
  2. c++

[解決済み] new'を使うとなぜメモリリークが起こるのか?

2022-06-29 22:07:18

質問

私はC#を最初に学び、今はC++を始めています。私が理解しているように、演算子 new はC#のものと似て非なるものです。

このサンプルコードでメモリリークが発生した理由を説明してください。

class A { ... };
struct B { ... };

A *object1 = new A();
B object2 = *(new B());

どのように解決するのですか?

何が起きているのか

と書くと T t; と書くと T 自動保存期間 . スコープ外になると自動的にクリーンアップされます。

と書くと new T() と書くと T 動的な保存期間 . 自動的にクリーンアップされることはありません。

にそのポインタを渡す必要があります。 delete にポインタを渡す必要があります。

しかし、2番目の例はもっと悪いです。ポインタを再参照して、オブジェクトのコピーを作っているのです。この方法では new で作成されたオブジェクトへのポインタを失ってしまうので、削除したくてもできないのです!

やるべきこと

ストレージの自動継続を選択すべきです。新しいオブジェクトが必要な場合は、ただ書き込むだけです。

A a; // a new object of type A
B b; // a new object of type B

動的な保存期間が必要な場合は、割り当てられたオブジェクトへのポインタを、自動的に削除する自動保存期間オブジェクトに保存してください。

template <typename T>
class automatic_pointer {
public:
    automatic_pointer(T* pointer) : pointer(pointer) {}

    // destructor: gets called upon cleanup
    // in this case, we want to use delete
    ~automatic_pointer() { delete pointer; }

    // emulate pointers!
    // with this we can write *p
    T& operator*() const { return *pointer; }
    // and with this we can write p->f()
    T* operator->() const { return pointer; }

private:
    T* pointer;

    // for this example, I'll just forbid copies
    // a smarter class could deal with this some other way
    automatic_pointer(automatic_pointer const&);
    automatic_pointer& operator=(automatic_pointer const&);
};

automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically

<イグ

これは一般的なイディオムで、RAIIというあまり説明的でない名前で呼ばれています( リソースの取得は初期化 ). クリーンアップが必要なリソースを取得したとき、それを自動保存期間のオブジェクトに貼り付けるので、クリーンアップについて心配する必要はありません。これは、メモリ、開いているファイル、ネットワーク接続など、どんなリソースにも当てはまります。

これは automatic_pointer のようなものは既に様々な形で存在しています。私はただ例を示すためにこれを提供しました。非常によく似たクラスが標準ライブラリに存在し std::unique_ptr .

という古いもの(C++11以前)もあります。 auto_ptr という名前の古いものもありますが、これは奇妙なコピー動作があるため、現在では非推奨となっています。

そして、さらにスマートな例として、例えば std::shared_ptr のように、同じオブジェクトへの複数のポインタを許可し、最後のポインタが破壊されたときだけそれをクリーンアップするような、さらに賢い例もあります。