【问题标题】:How to avoid memory leak with abstract class pointers如何使用抽象类指针避免内存泄漏
【发布时间】:2019-06-20 10:29:02
【问题描述】:

假设我有一个抽象类(下例中的“Book”)和一些派生类(下例中的“ElectroniBook”、“CodingBook”)。我还想在第三类(“图书馆”)中保留一个书籍矢量和一些地图来找到它们。我们还假设我需要使用“addBook”方法从其他地方创建“库”,然后在主目录中分配它。

由于 Book 是抽象的,我最终需要删除我创建的“Book”指针,并且我想在一些析构函数中执行此操作。尽管如此,每当我尝试使用删除时,我都会收到此错误消息

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

如果我尝试用 shared_pointers 或 unique_pointers 替换原始指针,我会在编译时立即收到错误消息,告诉我我正在尝试使用已被删除的指针。请注意,我使用的是 C++ 11。

以下是一些代码示例:

class Book{
public:
Book(string name, int Npages);
virtual ~Book();
virtual void displayBook() = 0;
private:
string _name;
int _Npages;
}


class ElectronicBook : public Book{
public:
ElectronicBook(string name, int Npages);
~ElectronicBook();
void displayBook() {  //do something 
                    };
}

class CodingBook : public Book{
public:
CodingBook(string name, int Npages);
~CodingBook();
void displayBook() { // do something  else
                    };
}


class Library{
public :
 Library();
~Library(){
 // this doesn't work for me
// for(auto & a : _books)
//    delete a;
//  _books.clear();
// 
//for(int i=0;i<_bookmap.size();++i)
//    delete bookmap.at(i);    
};

void addCodingBook(string name, int Npages){
CodingBook* cb = new CodingBook(name, Npages);
_books.push_back(cb);
_bookmap[name] = cb;

//should I delete anything here?
};

void addEletronicBook(string name, int Npages){
ElectronicBook* eb = new ElectronicBook(name, Npages);
_books.push_back(eb);
_bookmap[name] = eb;

//should I delete anything here?
};

private :
vector<Book*> _books;
map<string, Book*> bookmap;
}


// separeted function
Library createLibrary(){

    Library L;
    while(...){
     //read books from somewhere(file, input or whatever) and 
    // addElectronicBook(...) 
    // addCodingBook(...)
    }

 return L;
}


int main(){

Library myLibrary = createLibrary();
// do something with Library
}

由于我多次“新建”添加图书,我需要删除它们。我尝试像我展示的那样在库析构函数中执行此操作,但我得到了前面提到的错误。

【问题讨论】:

  • 在您的设置中完全避免使用指针。如果需要,请使用 shared_ptr。
  • "如果我尝试用 shared_pointers 或 unique_pointers 替换原始指针,我会在编译时立即收到错误消息,告诉我我正在尝试使用已被删除的指针。"一个不会删除智能指针 - 这在某种程度上违背了他们的目的。我建议您发布尝试使用它们的代码,因为这是正确的方法,但对您不起作用

标签: c++ class memory abstract


【解决方案1】:

如果我正确理解您的问题,您将释放两次相同的内存:

// for(auto & a : _books)
//    delete a;
//  _books.clear();
// 
//for(int i=0;i<_bookmap.size();++i)
//    delete bookmap.at(i); 

_books 和 bookmap 都包含指向相同内存区域的指针,并且您要释放它们两次。 使用原始指针时,您必须确定谁是内存的所有者,例如_books,以及谁可以简单地访问内存但不负责清理。 所以,你应该:

  1. 只删除一次,所以只使用两个 for 循环之一,比如为了参数_books

  2. 确保其他非拥有结构,例如我们示例中的 bookmap,在删除后永远不会访问内存(即取消引用指针)

建议:放入向量unique_ptr,使向量成为所有者,并在地图中放置原始指针以表示地图不拥有。 unique_ptr 会帮你清理内存。如果您想确定,添加一些打印语句或在析构函数中放置断点(如果您有调试器)。

【讨论】:

  • 谢谢,您的评论帮助我更好地理解。我使用了 shared_ptr 并且它有效。使用独特的 ptr 它没有,但您的帮助很宝贵:D
  • 如果你写unique_ptr有什么问题,我可以看看。告诉我。
  • 感谢您的帮助。这是表盘:如果我尝试用std::unique_ptr&lt;Book&gt; eb(new ElectronicBook(...)) 替换std::shared_ptr,我无法将eb 分配给我的地图。到处查看我想我需要使用insert 或std::make_unique(虽然在C++ 11 中不可用)。此外,它给了我错误消息called to deleted constructor ' ...' (aka ... ) note has been explicitly marked deleted here
  • 你不能复制一个 unique_ptr,因为它是独一无二的。你可以移动它。所以你可以做 _books.push_back(std::move(ptr)) 。在此 ptr 将指向 null 并且所有权转移到向量之后
  • 好的,我试试,谢谢。我是记忆问题的新手,我在学校里学过更多最近的编程语言,我以前从未关心过记忆。再次感谢!
猜你喜欢
  • 2020-05-03
  • 2017-10-31
  • 2011-03-27
  • 2010-12-22
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
相关资源
最近更新 更多