C++ 内存泄漏,Valgrind 消息误导?
C++ Memory Leak, Valgrind Message Misleading?
我对 C++ 有点陌生,我能够 运行 我的代码没有错误,但是,当我 运行 时,我 运行 陷入内存泄漏] 它通过 Valgrind,我似乎无法为我的生活找出我泄漏的地方!这是我的错误消息:
==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)
我有一个class,Foo,用作"attachments"到Barclass。 Bar继承自foo。它有两个private成员,id_和name_,析构函数和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;
当然,我可以根据要求上传整个程序(尽管我觉得问题可能很明显,我只是完全遗漏了一些东西)。任何帮助都会很棒!
您需要为 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中,你的析构函数已经很好了 已 声明为虚拟 以便派生的 class 析构函数在您的基础 class 析构函数之前被调用。由于派生的 class 具有动态内存,因此您希望发生这种情况。所以在 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)
};
尝试对 Foo Bar 对象使用 std::unique_ptr。
我对 C++ 有点陌生,我能够 运行 我的代码没有错误,但是,当我 运行 时,我 运行 陷入内存泄漏] 它通过 Valgrind,我似乎无法为我的生活找出我泄漏的地方!这是我的错误消息:
==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)
我有一个class,Foo,用作"attachments"到Barclass。 Bar继承自foo。它有两个private成员,id_和name_,析构函数和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;
当然,我可以根据要求上传整个程序(尽管我觉得问题可能很明显,我只是完全遗漏了一些东西)。任何帮助都会很棒!
您需要为 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中,你的析构函数已经很好了 已 声明为虚拟 以便派生的 class 析构函数在您的基础 class 析构函数之前被调用。由于派生的 class 具有动态内存,因此您希望发生这种情况。所以在 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)
};
尝试对 Foo Bar 对象使用 std::unique_ptr。