2

だから私はこのようになります基底クラス持っている:ベースクラスを変更せずに派生クラスのメモリリークを防ぐ方法はありますか?

class base { 
public: 
    base() { 
     std::cout << "We created a base!" << std::endl; 
    } 

    ~base() { 
     std::cout << "We destroyed a base!" << std::endl; 
    } 
}; 

をそして、私はこのようになります派生クラスがあります。今

class leaks_memory : public base { 
public: 
    leaks_memory(size_t count) : 
    memory(new int[count]), size_of_memory(count) 
    { 
     announce(); 
    } 

    leaks_memory(const leaks_memory & lm) : 
    leaks_memory(lm.size_of_memory) 
    { 
     std::copy(lm.memory, lm.memory + size_of_memory, memory); 
    } 

    void swap(leaks_memory & lm) noexcept { 
     std::swap(lm.memory, memory); 
     std::swap(lm.size_of_memory, size_of_memory); 
    } 

    leaks_memory(leaks_memory && lm) { 
     swap(lm); 
    } 

    leaks_memory & operator=(leaks_memory lm) { 
     swap(lm); 
     return *this; 
    } 

    ~leaks_memory() { 
     delete[] memory; 
     dennounce(); 
    } 

    int & operator[](size_t index) { 
     return memory[index]; 
    } 

    const int & operator[](size_t index) const { 
     return memory[index]; 
    } 
private: 
    int * memory; 
    size_t size_of_memory; 

    void announce() const noexcept { 
     std::cout << "We created a Leaks Memory!" << std::endl; 
    } 

    void dennounce() const noexcept { 
     std::cout << "We destroyed a Leaks Memory!" << std::endl; 
    } 
}; 

を、自分自身で、これらはありません問題は、私はこのようなコード書くまで:

int main() { 
    std::unique_ptr<base> base_ptr; 
    std::atomic_bool done = false; 
    std::thread input_thread{ [&done] { 
     std::getline(std::cin, std::string()); 
     done = true; 
    } }; 
    while (!done) { 
     base_ptr = std::make_unique<leaks_memory>(20'000); 
    } 
    input_thread.join(); 
    return 0; 
} 

leaks_memoryデストラクタが呼び出されることは決してありませんので、このコードが漏れは、ループのすべての反復を20KB!

今、明らかに、私はbaseに編集を行うことによって、この問題を解決することができます:

virtual ~base() { 
     std::cout << "We destroyed a base!" << std::endl; 
    } 

そして実際に、私はこの変更を行った後、同じコードを実行した場合、私はもはや、このメモリリークを持っていません。

しかし、baseクラスを編集できない場合はどうすればよいですか?実行中のコードの設計を完全に変更せずにメモリリークを防ぐ方法はありますか?

+3

基本クラスに 'virtual'デストラクタがあります。 –

+1

@πάνταῥεpromptプロンプト全体をお読みください。 'base'クラスを変更することなく*可能かどうか知りたいです。私はすでに、 'base'のデストラクタを仮想化することでそれを修正することを知っています。 – Xirema

+0

@πάνταῥεῖBTWデストラクタは常に仮想でなければなりません。 –

答えて

2

スマートポインタにはカスタムディレーターがあり、すべての階層のルートにバーチャルデストラクトを配置する必要はありません。

残念ながら、この機能は使用しにくいです。なぜなら、Deleterのタイプはshared_ptrとunique_ptrの両方のテンプレートパラメータであるからです。だから、最終的なオブジェクトの種類を隠すために、一つは型消去のビットを必要とする:

void derived_deleter(base* p) { delete static_cast<derived*>(p); } 

std::unique_ptr<base, decltype(&derived_deleter)> base_ptr (new derived, derived_deleter); 

STDを使用する方法:: make_uniqueはないように思えます。

+0

これはループの 'base_ptr(nullptr、nullptr)'と 'base_ptr.swap(temp_base_ptr)'とうまく機能します。 – wally

0

別のオプションは、あなたがconst参照して暮らすことができる場合は、次のベースへの参照を作成しますが、派生デストラクタを呼び出します"most important const"

を使用するかもしれません。

leaks_memory factory() 
{ 
    return leaks_memory(20'000); 
} 

int main() 
{ 
    //std::unique_ptr<base> base_ptr; 
    std::atomic_bool done = false; 
    std::thread input_thread{[&done] { 
     std::getline(std::cin, std::string()); 
     done = true; 
    }}; 
    while (!done) { 
     //base_ptr = std::make_unique<leaks_memory>(20'000); 
     const base& base_const_ref = factory(); 
    } 
    input_thread.join(); 
    return 0; 
} 
関連する問題