"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()
完成它的工作。
我想弄清楚我的 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()
完成它的工作。