2017-11-12 2 views
2

割り当ての場合I は、カスタムリストである必要があります。タイトルとして、nodes \ itemsのdeleteを呼び出していてもメモリリークが発生します。私はこれについて何か助けていただければ幸いです。 valgrindのカスタムリンクリストのメモリリークC++

==12125== 40 (24 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3 
==12125== at 0x4C29203: operator new(unsigned long) (vg_replace_malloc.c:334) 
==12125== by 0x400FD8: DLinkList<Foo*>::push_back(Foo*) (DLinkList.hpp:138) 
==12125== by 0x400CF3: main (Source.cpp:28) 

から

リストソース

template <typename T> 
class DLinkList 
{ 
private: 
    struct Node 
    { 
     T data; 
     Node *nextNode; 
     Node *prevNode; 
     Node(T data, Node *nextNode = nullptr, Node *prevNode = nullptr) 
     { 
      this->data = data; 
      this->nextNode = nextNode; 
      this->prevNode = prevNode; 
     } 
     ~Node() { delete data; } 
    }; 

    Node *head; 
    Node *tail; 

public: 
    DLinkList(); 
    ~DLinkList(); 

    void push_back(T data); 
}; 

template <typename T> 
inline void DLinkList<T>::push_back(T data) 
{ 
    if (isEmpty()) 
    { 
     head = new Node(data); 
     tail = head; 
    } 
    else 
    { 
     tail->nextNode = new Node(data, nullptr, tail); 
     tail = tail->nextNode; 
    } 
} 

template <typename T> 
DLinkList<T>::DLinkList() 
{ 
    head = nullptr; 
    tail = nullptr; 
} 

template <typename T> 
DLinkList<T>::~DLinkList() 
{ 
    Node *ptr = head; 
    while (ptr->nextNode != nullptr) 
    { 
     Node *garbage = ptr; 
     ptr = ptr->nextNode; 
     delete garbage; 
    } 
} 

のFooクラスとメイン

class Foo 
{ 
public: 
    Foo() { i = 0; d = 0.0; } 
    Foo(int i, double d) { this->i = i; this->d = d; } 

    int getInteger() { return i; } 
    double getDouble() { return d; } 

private: 
    int i; 
    double d; 
}; 


int main() 
{ 
    DLinkList<Foo*> f1; 
    f1.push_back(new Foo()); 
    f1.push_back(new Foo(2, 5.5)); 

    cout << "1st Values: " << f1.at(0)->getInteger() << ", " << f1.at(0)->getDouble() << endl; 
    cout << "2nd Values: " << f1.at(1)->getInteger() << ", " << f1.at(1)->getDouble() << endl; 

    return 0; 
} 

私はそれを言いたい、メモリはここで失われているかどうかはわかりませんよそれはそれをコピーしており、元のものが失われているからです。この場合、私はそれをどのように扱うのかよくわかりません。

もう一度ご理解いただきありがとうございます。私は関連するすべての質問を調べようとしましたが、これをカバーするものは見当たりませんでした。少なくとも私はそれを理解しませんでした。ありがとうございました!

f1.push_back(new Foo()); 
f1.push_back(new Foo(2, 5.5)); 

あなたがそれらにここにインスタントメモリリークを作成している。他の問題は、このような明示的DLinkListデストラクタを呼び出すの誤った使い方をするようなコメントで指摘し、あなたがmain()でこれをやっている考える

+0

私の推測では、あなたは 'T'にどのようなタイプを使用しているかによって異なります。おそらく 'Node'のデストラクタが役に立ちます。 – klutt

+0

私はそれを試しました。データの削除と呼ばれ、valgrindは4つのallocs、4つの解放を示します - しかし、私はまだ同じメッセージで漏れがあります。 –

+1

@MasonR 'f1。〜DLinkList();' - なぜあなたはこれをやっていますか?オブジェクトのデストラクタは、オブジェクトがスコープから外れると自動的に呼び出されます。あなたがここでやっているのは、C++デストラクタの動作を妨害することによってメモリ破壊を引き起こすことだけです。その行を取り除き、正しいコピーセマンティクスを持つようにクラスを修正してください(あなたのプログラムは 'DLinkList'を別の' DLInkList'に割り当てるだけで簡単に破壊されます)。 – PaulMcKenzie

答えて

1

2行のコードは回復できません。あなたはnewに電話していますが、newから返された住所は保存しないでください。後でその住所にdeleteを呼び出すことができます。

したがって、これらの動的に割り当てられたFooオブジェクトを管理する必要があるのはmainです。

Foo* p1 = new Foo(); 
Foo *p2 = new Foo(2, 5.5); 
f1.push_back(p1); 
f1.push_back(p2); 
//... 
delete p1; 
delete p2; 

これはメモリリークに対処する必要がありますが、これはC++のこの日と年齢でプログラミングが貧弱なことです。あなたはより多く

DLinkList<Foo> 

を使用するので、mainに手動メモリ管理を必要としない、リンクリストにFooオブジェクトを配置、またはスマートポインタを使用し、スマートポインタのリンクリストを持っている、すなわち

いずれかの可能性が高いだろう
DLinkList<std::unique_ptr<Foo>> 
+0

ありがとうございます。私は通常、ベクトルとリストを使用して、メインループを単純なループでクリーンアップします。私はそれを第一と第二の方法で試してきましたが、何らかの理由でそれがまだ漏れています。私はスマートポインタで試してみませんでしたが、どちらかを使用すると思われませんでした:( –

+0

メモリリークの修正方法については下記の回答を参照してください。PaulMcKenzieが多くの良いポイントもメモリリークに寄与しました。ありがとうPaulMcKenzie! –

0

申し訳ありませんので、私は疲れており、最も単純なものが欠けていました。作成した他のリストと比較した結果、デストラクタがノードを正しく削除していないことに気付きました。

template <typename T> 
DLinkList<T>::~DLinkList() 
{ 
    Node *ptr = head; 
    while (ptr != nullptr) // Not: ptr->nextNode 
    { 
     Node *garbage = ptr; 
     ptr = ptr->nextNode; 
     delete garbage; 
    } 
} 

しかし、私はPaulMcKenzieに感謝したいですが、大きな助けたともメインは、新しいコールの削除を処理する必要がないことを指摘しました。私は彼に投票してそれに印をつけます。