正确管理创建包含指针的双链接列表



(注意:我是新手。)我有一个函数可以创建一个双链接列表,其中包含Representative*的DNode,每个Representation有3个对象(字符串名称、int访问次数、int捐赠次数),并且内存泄漏。

运行程序后,我收到以下内存泄漏消息:

https://textuploader.com/51tme

我在valgrind的记忆检查中也有类似的错误。在我创建新Representative的5次中,每条消息似乎都被触发了两次(总共有10次内存泄漏)。列出的函数始终是addToList()中的运算符new。下面是addToList()函数:

bool ListManager::addToList(string rep_list){
    istringstream convertRepresentative(rep_list);
    string whitespaces(" tfvnr");
    size_t found = rep_list.find_first_not_of(whitespaces);
    if (rep_list.empty() || found == string::npos){
        /* string is empty or only has whitespace */
        cout << "n| ERROR(addToList()): String is empty. No representatives added to list.n| Function halted.n";
        return false;
    }
    string name;
    int visits;
    int donations;
    Representative* temp; // comment out if using shared_ptr
    if (convertRepresentative.fail()){
        /* error in string input */
        cout << "n| ERROR(addToList()): Could not import string. No representatives added to list.n| Function halted.n";
        convertRepresentative.clear();
        return false;
    }
    else{
        while (!convertRepresentative.eof()){
            if (!(convertRepresentative >> name)){
                cout << "n| ERROR(addToList()): Could not import string. Incorrect format.n| No representatives added to list. Function halted.n";
                rep_list.clear();
                convertRepresentative.clear();
                return false;
            }
            if (!(convertRepresentative >> visits)){
                cout << "n| ERROR(addToList()): Could not import string. Incorrect format.n| No representatives added to list. Function halted.n";
                rep_list.clear();
                convertRepresentative.clear();
                return false;
            }
            if (!(convertRepresentative >> donations)){
                cout << "n| ERROR(addToList()): Could not import string. Incorrect format.n| No representatives added to list. Function halted.n";
                rep_list.clear();
                convertRepresentative.clear();
                return false;
            }
            temp = new Representative(name, visits, donations);
            ListDLL.insertTail(temp);
            //shared_ptr<Representative> temp;
            //temp.reset(new Representative(name, strength, speed));
            //RosterDLL.insertTail(&*temp);
        }
        convertRepresentative.clear();
        return true;
    }
}

假设我将在某个时刻删除temp,但删除temp会删除DNode内的Representative数据。所以我不知道什么时候该删除temp和/或重置/清除它,不管怎样。正如你在我的注释代码中看到的,我尝试过智能指针,但它们做了我刚才描述的事情——它们从DNode中删除了所需的信息。

我是新手&我知道你们对格式等要求很严格(很抱歉我的#includenamespacestd)。我希望这是一个简单的解决方案。请帮忙。

编辑:根据建议,这里是DoubleLinkedList.h(您可以在第一个链接中看到该项目使用的所有文件):

#ifndef DOUBLELINKEDLIST_H_
#define DOUBLELINKEDLIST_H_
#include <stdexcept>
#include <iostream>
#include "Representative.h"
using namespace std;
struct DNode{
    Representative* rep;
    DNode* next;
    DNode* prev;
    DNode(Representative*& rep,
        DNode* prev_val = NULL, DNode* next_val = NULL) :
        rep(rep), next(next_val), prev(prev_val) {}
};
template<class T>
class DoubleLinkedList
{
public:
    DNode* head;
    DNode* tail;
    int count;
    DoubleLinkedList() :
        head(NULL), count(0),
        tail(NULL){
    }
    virtual ~DoubleLinkedList() {
        clear();
    }
    bool find(Representative* rep){
        bool found = false;
        if (head == NULL) {
            return found;
        }
        DNode* DNode_ptr = head;
        while (DNode_ptr != NULL){
            if (DNode_ptr->rep == rep){
                found = true;
            }
            DNode_ptr = DNode_ptr->next;
        }
        return found;
    }
    void insertTail(Representative* rep) {
        if (find(rep) == false) {
            if (head == NULL) {
                DNode* newDNode = new DNode(rep);
                head = newDNode;
                count++;
                return;
            }
            else {
                DNode* temp = head;
                while (temp->next != NULL) {
                    temp = temp->next;
                }
                DNode* tailDNode = new DNode(rep);
                temp->next = tailDNode;
                tailDNode->next = NULL;
                tailDNode->prev = temp;
                count++;
                return;
            }
        }
        else {
            return;
        }
    }
    Representative* at(int index){
        DNode* temp_ptr = head;
        if (index < 0 || index > count - 1){
            throw out_of_range("Out of Range");
        }
        else {
            for (int i = 0; i < index; i++){
                temp_ptr = temp_ptr->next;
            }
            return temp_ptr->rep;
        }
    }
        int size(){
        return count;
    }
        void clear(){
            DNode* temporary_ptr = head;
            while (temporary_ptr != NULL){
                DNode* tmp_pointer = temporary_ptr;
                temporary_ptr = temporary_ptr->next;
                delete tmp_pointer;
            }
            count = 0;
            head = NULL;
            return;
        }
 //Rest of functions omitted
};
#endif /* DOUBLELINKKEDLIST_H_ */

啊,我现在看到了。分配一个Representative,然后将分配的指针存储在分配的DNode中。当您clearDoubleLinkedList时,这将删除DNodes,但不会删除存储在其中的已分配的Representatives,这会导致泄漏。

更好的解决方案是在列表中存储Representative,而不是Representative *

如果你能在C++11下编译,考虑到编译器对它的高度支持,你应该能够,你根本不应该使用原始指针来管理内存。

如果您不想传输大量数据,并且正在创建自己的类,那么您甚至不需要首先使用指针。只需实现move构造函数和move-assignment运算符,并使用常规值对象而不是指向它们的指针。

如果您真的需要使用指针——例如,可以创建某种库的对象集合,即没有实现move构造函数和move-assignment运算符的对象——请使用<memory>标头中的std::unique_ptr<T>std::shared_ptr<T>。您不需要调用delete,因为智能指针会处理它。

相关内容

  • 没有找到相关文章

最新更新