C ++内存泄漏,Valgrind消息误导?

时间:2017-03-22 01:43:09

标签: c++ valgrind

我对C ++并不陌生,而且我能够毫无错误地运行我的代码,但是,当我通过Valgrind运行时,我遇到内存泄漏,我可以&#39因为我的生活似乎在弄清楚我在哪里泄漏!这是我的错误信息:

==22902==     in use at exit: 72,728 bytes in 2 blocks
==22902==   total heap usage: 4 allocs, 2 frees, 73,816 bytes allocated
==22902==
==22902== 24 bytes in 1 blocks are definitely lost in loss record 1 of 2
==22902==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22902==    by 0x401086: Bar::Bar(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) (Bar.cpp:10)
==22902==    by 0x400F76: main (Foo_main.cpp:20)

我有一个班级,Foo,用作&#34;附件&#34;到酒吧班。 Bar继承自foo。它有两个私有成员,id_和nam​​e_,析构函数和use()在头文件中声明为virtual。

#include "Foo.h"

#include<iostream>

using std::cout;
using std::endl;
using std::string;

Foo::Foo(int id, const string& name) :
        id_(id),
        name_(name){}

Foo::~Foo() {}

int Foo::id() const { return id_; }

string Foo::name() const { return name_; }

void Foo::use() const {
    cout << "Using Foo #" << id_ << ", " << name_ << endl;
}

Bar有两个私有成员,num_attachments_(unsigned int)和attachments_(Foo **)

#include "Bar.h"
#include <iostream>

using std::cout;
using std::endl;

Bar::Bar(int id, const std::string& name, unsigned int num_attachments) :
        Foo(id, name),
        attachments_(new Foo*[num_attachments]),
        num_attachments_(num_attachments) {
    // explicity null out each entry in the new array
    for (unsigned int i=0; i<num_attachments; ++i) {
        attachments_[i] = NULL;
    }
}

void Bar::use() const {
    cout << "Using Bar #" << id() << endl;
    for (unsigned int i=0; i<num_attachments_; ++i) {
        if (attachments_[i] != NULL) {
            attachments_[i]->use();
        }
    }
}

(注意:我所知道的一些代码不会导致泄漏被注释掉)。 我怀疑问题出在Bar的use()函数中,但我不太确定缺少什么!

最后,这是主要功能:

Foo* f = new Bar(1, "foobar", 3);
f->use();
delete f;

当然,我可以根据要求上传整个程序(虽然我觉得这个问题可能很明显,而且我完全错过了一些东西)。任何帮助都会很棒!

2 个答案:

答案 0 :(得分:1)

您需要为Bar

声明并实现显式析构函数

可能必须发生内存泄漏,因为您尚未释放属性attachments_的内存,必须在Bar构造函数中分配。

它的析构函数应该类似于这样实现:

Bar::~Bar() {
    for (unsigned int i = 0; i < num_attachments_; i++) {
        if (attachments_[i] != NULL) {
            delete attachments_[i];
        }
    }
    if(attachments_) { // Just a safeguard good practice for defensive programming. You could omit this statement. This if statement is the same as if (attachments_ != NULL)
        delete [] attachments_;
    }
}

此外,由于Bar继承自Foo,在 Bar.h 析构函数已经已经很好了声明为虚拟,以便在基类的析构函数之前调用派生类析构函数。由于派生类具有动态内存,因此您希望该场景发生。所以在 Bar.h

class Bar: public Foo {
   /* ...other class members... */
   public:
       /* ...other class operations... */
       virtual ~Bar(); // the virtual keyword here forces the program to visit Bar's (the derived class) destructor before Foo's (the base class)destructor. It is necessary, otherwise it only invokes the Foo's destructor (leaving leaked dynamic memory from Bar)
};

答案 1 :(得分:0)

尝试将std :: unique_ptr用于Foo Bar对象。

http://en.cppreference.com/w/cpp/memory/unique_ptr