"blocks are indirectly lost in loss record.." valgrind 错误 - cpp

"blocks are indirectly lost in loss record.." valgrind error - cpp

我想弄清楚我的 cpp 代码有什么问题,我需要你的帮助!

valgrind 输出

错误出现在这里(在测试文件中): list = list.apply(getLen);

函数getLen:

string getLen(string str)
{
    return std::to_string(str.length());
}

通用函数应用:

template<class T>
    template<class Operation>
    SortedList<T> SortedList<T>::apply(Operation operation) const{//TODO: 6 blocks are indirectly lost.

        Node<T>* current_node_to_check = head;
        SortedList<T> new_sorted_list;

        for (int i = 0; i < list_length; ++i) {
            T result = operation(current_node_to_check->info);
            new_sorted_list.insert(result);
            current_node_to_check = current_node_to_check->next;
        }

        return new_sorted_list;
    }

节点结构实现:

template<class T>
    struct Node{
        T info;
        Node<T>* next;

        explicit Node(const T& new_info) : info(new_info), next(nullptr){}

    };

测试文件:

#include <iostream>
#include "SortedList.h"
#include "examDetails.h"

using std::cout;
using std::endl;
using std::string;
using namespace mtm;

#define TEST(num) cout << endl << "TEST " << (num) << endl;

string getLen(string str)
{
    return std::to_string(str.length());
}

bool isTrollLink(const ExamDetails& exam) {
    return (exam.getLink().find("tinyurl") != string::npos);
}

template<class T>
void printList(SortedList<T> list) {
    for (auto it = list.begin(); !(it == list.end()); ++it) {
        cout << *it << endl;
    }
    cout << endl;
}

int main()
{
    .
    .
    .

    TEST("1.5")
    SortedList<string> lst1 = SortedList<string>();
    lst1.insert("Charlie");
    lst1.insert("Bob");
    lst1.insert("Alice");
    lst1.insert("Donald");

    printList(lst1);

    TEST("1.6")
    SortedList<ExamDetails> lst2;
    lst2.insert(exam1);
    lst2.insert(exam2);

    printList(lst2);

    TEST("1.7")
    SortedList<string> lst3 = lst1;
    printList(lst3);

    TEST("1.8")//TODO: 6 blocks are indirectly lost.
    lst3 = lst3.apply(getLen);
    printList(lst3);


    TEST("1.9")
    lst3.remove(lst3.begin());
    printList(lst3);

    TEST("1.10")
    SortedList<ExamDetails> lst4 = lst2.filter(isTrollLink);
    printList(lst2);
    cout << "----------" << endl;
    printList(lst4);

    return 0;
}

通用 class 文件:


#ifndef NEW_SORTED_LIST_SORTEDLIST_H
#define NEW_SORTED_LIST_SORTEDLIST_H

#include <stdexcept>

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

namespace mtm {

    template<class T>
    struct Node{
        T info;
        Node<T>* next;

        explicit Node(const T& new_info) : info(new_info), next(nullptr){}

    };

    template<class T>
    class SortedList {
    private:
        Node<T>* head;
        int list_length;
        static const int empty = 0;
        void deleteNodes();

    public:

        class const_iterator;

        SortedList();

        ~SortedList();

        SortedList(const SortedList &to_copy);

        SortedList& operator=(const SortedList &to_assign);

        void insert(const T &to_insert);

        void remove(const const_iterator& iterator);

        int length() const;

        template<class Condition>
        SortedList filter(Condition condition) const;

        template<class Operation>
        SortedList apply(Operation operation) const;



        const_iterator begin() const;
        const_iterator end() const;

    };

    template<class T>
    class SortedList<T>::const_iterator{

        const SortedList<T>* sortedListPointer;
        int index;

        const_iterator(const SortedList<T>* sortedListPointer, int index) : sortedListPointer(sortedListPointer),
                                                                            index(index){}
        friend class SortedList<T>;
        static const int first = 1;

    public:

        const_iterator(const const_iterator&) = default;

        const_iterator& operator=(const const_iterator&) = default;

        const T& operator*(){
            if (index > sortedListPointer->length()+1 || index<0){
                throw std::out_of_range("error: iterator out of range");//TODO
            }
            Node<T>* current = sortedListPointer->head;
            for (int i = 1; i < index; ++i) {
                current = current->next;
            }
            return current->info;
        }

        const_iterator& operator++() {

            ++index;
            if (index > sortedListPointer->length()+1){
                throw std::out_of_range("error: iterator out of range");//TODO
            }
            return *this;
        }

        const_iterator operator++(int){

            SortedList<T>::const_iterator result = *this;
            ++*this;
            return result;
        }

        bool operator==(const const_iterator& it) const{

            return (index == it.index);
        }

    };

    template<class T>
    typename SortedList<T>::const_iterator SortedList<T>::begin() const{
        return const_iterator(this, const_iterator::first);
    }

    template<class T>
    typename SortedList<T>::const_iterator SortedList<T>::end() const{
        return const_iterator(this, this->length()+1);
    }

    template<class T>
    SortedList<T>::SortedList() : head(nullptr), list_length(empty){}

    template<class T>
    SortedList<T>::~SortedList() {

        deleteNodes();
    }

    template<class T>
    SortedList<T>::SortedList(const SortedList& to_copy){

        Node<T>* current_to_copy = to_copy.head;
        Node<T>* current = nullptr;
        Node<T>* new_head;

        if (to_copy.list_length == 0){
            return;
        }else{
            Node<T>* new_node = new Node<T>(current_to_copy->info);
            //exception
            //new_node->info = current_to_copy->info;
            //new_node->next = nullptr;

            current = new_node;
            current_to_copy = current_to_copy->next;
            new_head = current;
        }
        while (current_to_copy){

            Node<T>* new_node = new Node<T>(current_to_copy->info);
            //exception
            //new_node->info = current_to_copy->info;
            //new_node->next = nullptr;

            current->next = new_node;
            current = current->next;
            current_to_copy = current_to_copy->next;
        }
        list_length = to_copy.list_length;
        head = new_head;
    }

    template<class T>
    void SortedList<T>::deleteNodes(){

        if (list_length == empty){
            head = nullptr;
            return;
        }
        Node<T>* current = head->next;
        for (int i = 1; i < list_length; ++i) {
            Node<T>* previous = head;
            Node<T>* temp = current->next;
            delete current;
            current = temp;
            previous->next = current;
        }
        delete head;
        head = nullptr;
        list_length = empty;
    }

    template<class T>
    SortedList<T>& SortedList<T>::operator=(const SortedList &to_assign){

        if (this == &to_assign){
            return *this;
        }

        head = nullptr;
        Node<T>* current_to_assign = to_assign.head;
        Node<T>* current;
        Node<T>* new_head;

        if (current_to_assign){
            Node<T>* first_node = new Node<T>(current_to_assign->info);
            current = first_node;
            current_to_assign = current_to_assign->next;
            new_head = first_node;
        }else{
            deleteNodes();
            head = nullptr;
            return *this;
        }

        while (current_to_assign){

            Node<T>* new_node = new Node<T>(current_to_assign->info);

            current->next = new_node;
            current = current->next;
            current_to_assign = current_to_assign->next;
        }

        head = new_head;
        list_length = to_assign.list_length;
        return *this;
    }

    template<class T>
    void SortedList<T>::insert(const T &to_insert){

        Node<T>* new_node = new Node<T>(to_insert);

        Node<T>* current = head;
        if (!current){
            head = new_node;
            list_length++;
            return;
        }
        Node<T>* previous = head;
        if (current->info < to_insert){
            current = current->next;
        }else{
            new_node->next = current;
            head = new_node;
            list_length++;
            return;
        }
        while (current){
            if (current->info < to_insert){
                current = current->next;
                previous = previous->next;
            }else{
                new_node->next = current;
                previous->next = new_node;
                list_length++;
                return;
            }
        }

        previous->next = new_node;
        list_length++;
    }

    template<class T>
    void SortedList<T>::remove(const SortedList<T>::const_iterator& iterator){

        if (list_length == 1){
            list_length--;
            delete head;
        }

        int index = iterator.index;
        if (index == 1){
            Node<T>* temp = head->next;
            delete head;
            head = temp;
            list_length--;
            return;
        }
        Node<T>* current = head;
        Node<T>* previous = nullptr;
        for (int i = 1; i < index-1; ++i) {

            if ((i+1) == index-1){
                previous = current;
            }
            current = current->next;
        }

        previous->next = current->next;
        delete current;//TODO destructor(?)
        list_length--;
    }

    template<class T>
    int SortedList<T>::length() const{
        return list_length;
    }

    template<class T>
    template<class Condition>
    SortedList<T> SortedList<T>::filter(Condition condition) const{

        Node<T>* current_node_to_check = head;
        SortedList<T> new_sorted_list;

        for (int i = 0; i < list_length; ++i) {
            if (condition(current_node_to_check->info)){
                new_sorted_list.insert(current_node_to_check->info);
            }
            current_node_to_check = current_node_to_check->next;
        }
        return new_sorted_list;
    }

    template<class T>
    template<class Operation>
    SortedList<T> SortedList<T>::apply(Operation operation) const{//TODO: 6 blocks are indirectly lost.

        Node<T>* current_node_to_check = head;
        SortedList<T> new_sorted_list;

        for (int i = 0; i < list_length; ++i) {
            T result = operation(current_node_to_check->info);
            new_sorted_list.insert(result);
            current_node_to_check = current_node_to_check->next;
        }

        return new_sorted_list;
    }

}

#endif //NEW_SORTED_LIST_SORTEDLIST_H

没有测试 1.8,代码运行良好,完全没有错误! 我应该怎么做才能解决它? 谢谢

您在 main() 中分配了一个 SortedList<string> 对象,它分配了内存但从未释放它。

其他块属于列表中的 std::string 个对象。它们丢失只是因为保存它们的列表丢失了它们。

分析时,不要担心间接丢失的6块,关注直接丢失的块。

几乎可以肯定这违反了“五律”。您的 SortedList 在其构造函数中进行了分配,但未在其移动赋值运算符中正确管理该分配。


查看复制赋值运算符中的代码,这一行导致泄漏

head = nullptr;

不需要它,您稍后调用 deleteNodes() 无论如何都会这样做,并且通过事先擦除 head 可以防止 deleteNodes() 完成它的工作。