嗨,我有一个链表实现,我在valgrind中得到了内存泄漏错误...最初有4个但是在修复它之后,我仍然得到两个。
头:
class LL1{
public:
LL1(); //default construtor
LL1(const LL1& lst); //copy constructor
~LL1();//destructor
void add(int data);
void insertAt(int pos, int data);
bool remove(int data );
void removeAll();
// Empties the list.
void printList();
// Prints the contents of the list to the screen, in order
private:
// List node
struct Node {
int data; //list data
Node *next; //pointer to next item in the list
};
Node *head; //Pointer to the first node in the list
int size; //Records the number of nodes in the list
};
implemen:
// Implementation of the LinkedList class
// Version 1: Full of memory leaks.
#include "LL1.h"
#include <string>
#include <iostream>
using namespace std;
// Default constructor
LL1::LL1(){
head = NULL;
size = 0;
}
LL1::LL1(const LL1& lst){
head = lst.head; //shallow copy - this is an error!
size = lst.size;
}
// Destructor.
LL1::~LL1(){
Node *ptr=head;
Node *temp;
while (ptr != NULL)
{
temp = ptr->next;
delete ptr;
ptr = temp;
}
}
/**************************************************************************/
// Operations
void LL1::add(int x){
Node *p = new Node; //temporary node
// Assign appropriate values to the new node
p -> data = x;
p -> next = head;
// Make the head point to the new node
head = p;
size++;
}
void LL1::insertAt(int pos, int x){
Node *p;
Node *newNode;
// Check that pos is a valid index
if (pos <= size){
newNode = new Node; //new node
newNode->data = x;
if (pos == 0){
newNode->next = head;
head = newNode;
}// if(pos == 0)
else{
p = head;
// Move to position BEFORE insertion point
for(int i = 0; i < pos-1; i++){
if(p == NULL){
return;
}
p = p->next;
}//for
// Insert node
newNode->next = p->next;
p->next = newNode;
}//else (pos != 0)
size++;
}//else (pos >= size) do nothing
}
bool LL1::remove(int x){
Node *p = head;
// Check to see if the list exists
if (head == NULL){
return false;
}
else if (head->data == x){
head = head->next;
size--;
return true;
}
// Otherwise iterate through list
else{
while(p->next != NULL){
// Check next node for target
if(p->next->data == x){
p->next = p->next->next;
return true;
size-- ;
}
p = p->next;
}
}
return false;
}
// Empties the list.
void LL1::removeAll(){
head = NULL;
size = 0;
}
void LL1::printList(){
Node *p = head;
cout << "["; //Nice format!
// Traverse the list
while (p != NULL){
cout << p -> data; // Print data
p = p -> next; // Go to next node
if (p != NULL){
cout << ","; // Print a comma unless at the end of the list
}
}
cout << "]"; // Don't print a newline - it might not be wanted
}
测试/主文件:
#include "LL1.h"
#include <iostream>
using namespace std;
void listTest();
int main() {
cout << "!!!Hello!!!" << endl;
listTest();
cout << "!!!Goodbye!!!" << endl;
return 0;
}
void listTest(){
cout << "A little exercise with memory leaks in the LL1 linked list class." << endl << endl ;
cout << "List1 and List1A are empty LL1 instances in heap memory." << endl;
LL1 * ls1;
LL1 * ls1A;
ls1 = new LL1();
ls1A = new LL1();
cout << "Add 1,2,3,4 to List1 and List1A." << endl;
ls1->add(1);
ls1->add(2);
ls1->add(3);
ls1->add(4);
ls1A->add(1);
ls1A->add(2);
ls1A->add(3);
ls1A->add(4);
cout << "List1 is:"; ls1->printList(); cout << endl << endl;
cout << "List1A is:"; ls1A->printList(); cout << endl << endl;
cout << "Remove some items from List1" << endl;
ls1->remove(2);
ls1->remove(4);
cout << "List1 is:" ; ls1->printList() ; cout << endl ;
cout << "Now, empty List1 with removeAll" << endl ;
ls1->removeAll();
cout << "List1 is:" ; ls1->printList() ; cout << endl ;
cout << endl ;
cout << "That's all!" << endl;
delete ls1;
delete ls1A;
}
valgrind错误:
==25924== Memcheck, a memory error detector
==25924== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25924== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==25924== Command: ./test
==25924==
!!!Hello!!!
A little exercise with memory leaks in the LL1 linked list class.
List1 and List1A are empty LL1 instances in heap memory.
Add 1,2,3,4 to List1 and List1A.
List1 is:[4,3,2,1]
List1A is:[4,3,2,1]
Remove some items from List1
List1 is:[3,1]
Now, empty List1 with removeAll
List1 is:[]
That's all!
!!!Goodbye!!!
==25924==
==25924== HEAP SUMMARY:
==25924== in use at exit: 64 bytes in 4 blocks
==25924== total heap usage: 10 allocs, 6 frees, 160 bytes allocated
==25924==
==25924== 32 (16 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 4
==25924== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25924== by 0x400E4E: LL1::add(int) (in /home/mani/Desktop/lab3/test)
==25924== by 0x400B34: listTest() (in /home/mani/Desktop/lab3/test)
==25924== by 0x400A51: main (in /home/mani/Desktop/lab3/test)
==25924==
==25924== 32 (16 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==25924== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25924== by 0x400E4E: LL1::add(int) (in /home/mani/Desktop/lab3/test)
==25924== by 0x400B56: listTest() (in /home/mani/Desktop/lab3/test)
==25924== by 0x400A51: main (in /home/mani/Desktop/lab3/test)
==25924==
==25924== LEAK SUMMARY:
==25924== definitely lost: 32 bytes in 2 blocks
==25924== indirectly lost: 32 bytes in 2 blocks
==25924== possibly lost: 0 bytes in 0 blocks
==25924== still reachable: 0 bytes in 0 blocks
==25924== suppressed: 0 bytes in 0 blocks
==25924==
==25924== For counts of detected and suppressed errors, rerun with: -v
==25924== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
答案 0 :(得分:0)
// Empties the list. void LL1::removeAll(){ head = NULL; size = 0; }
嗯,它将它遗忘,但不是那么干净。
此
void LL1::removeAll(){
//the LL1 dtor code
Node *ptr=head;
Node *temp;
while (ptr != NULL) {
temp = ptr->next;
delete ptr;
ptr = temp;
// and
--size;
}
}
会干净地清空清单,并可能让valgrind更快乐。
最好将其从dtor上移开,然后从那里拨打电话LL1::removeAll()
。
#include <string>
#include <iostream>
using namespace std;
class LL1 {
public:
LL1(); //default construtor
LL1(const LL1& lst); //copy constructor
~LL1();//destructor
void add(int data);
void insertAt(int pos, int data);
bool remove(int data );
void removeAll();
// Empties the list.
void printList();
// Prints the contents of the list to the screen, in order
private:
// List node
struct Node {
int data; //list data
Node *next; //pointer to next item in the list
};
Node *head; //Pointer to the first node in the list
int size; //Records the number of nodes in the list
};
// Implementation of the LinkedList class
// Version 1: Full of memory leaks.
using namespace std;
// Default constructor
LL1::LL1() {
head = NULL;
size = 0;
}
LL1::LL1(const LL1& lst) {
head = lst.head; //shallow copy - this is an error!
size = lst.size;
}
// Destructor.
LL1::~LL1() {
removeAll();
}
/**************************************************************************/
// Operations
void LL1::add(int x) {
Node *p = new Node; //temporary node
// Assign appropriate values to the new node
p -> data = x;
p -> next = head;
// Make the head point to the new node
head = p;
size++;
}
void LL1::insertAt(int pos, int x) {
Node *p;
Node *newNode;
// Check that pos is a valid index
if (pos <= size) {
newNode = new Node; //new node
newNode->data = x;
if (pos == 0) {
newNode->next = head;
head = newNode;
}// if(pos == 0)
else {
p = head;
// Move to position BEFORE insertion point
for(int i = 0; i < pos-1; i++) {
if(p == NULL) {
return;
}
p = p->next;
}//for
// Insert node
newNode->next = p->next;
p->next = newNode;
}//else (pos != 0)
size++;
}//else (pos >= size) do nothing
}
bool LL1::remove(int x) {
Node *p = head;
// Check to see if the list exists
if (head == NULL) {
return false;
}
else if (head->data == x) {
//Node* p = head;
head = head->next;
delete p;
--size;
return true;
}
// Otherwise iterate through list
else {
while(p->next != NULL) {
// Check next node for target
if(p->next->data == x) {
p->next = p->next->next;
size-- ;
return true;
}
p = p->next;
}
}
return false;
}
// Empties the list.
void LL1::removeAll() {
Node *temp;
while (head != NULL) {
temp = head->next;
delete head;
head = temp;
--size;
}
}
void LL1::printList() {
Node *p = head;
cout << "["; //Nice format!
// Traverse the list
while (p != NULL) {
cout << p -> data; // Print data
p = p -> next; // Go to next node
if (p != NULL) {
cout << ","; // Print a comma unless at the end of the list
}
}
cout << "]"; // Don't print a newline - it might not be wanted
}
void listTest();
int main() {
cout << "!!!Hello!!!" << endl;
listTest();
cout << "!!!Goodbye!!!" << endl;
return 0;
}
void listTest() {
cout << "A little exercise with memory leaks in the LL1 linked list class." << endl << endl ;
cout << "List1 and List1A are empty LL1 instances in heap memory." << endl;
LL1 * ls1;
LL1 * ls1A;
ls1 = new LL1();
ls1A = new LL1();
cout << "Add 1,2,3,4 to List1 and List1A." << endl;
ls1->add(1);
ls1->add(2);
ls1->add(3);
ls1->add(4);
ls1A->add(1);
ls1A->add(2);
ls1A->add(3);
ls1A->add(4);
cout << "List1 is:";
ls1->printList();
cout << endl << endl;
cout << "List1A is:";
ls1A->printList();
cout << endl << endl;
cout << "Remove some items from List1" << endl;
ls1->remove(2);
ls1->remove(4);
{
cout << "List1 is:" ;
ls1->printList() ;
cout << endl ;
cout << "Now, empty List1 with removeAll" << endl ;
ls1->removeAll();
cout << "List1 is:" ;
ls1->printList() ;
cout << endl ;
cout << endl ;
cout << "That's all!" << endl;
}
delete ls1;
delete ls1A;
}
使用g ++编译(Debian 4.9.2-10)4.9.2在linux 3.16.0-4-amd64上
与
g ++ -Wall -pedantic -g list2.cpp
在valgrind-3.10.0下运行
与
valgrind -v ./aout
给出
[...]
==18230== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==18230== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)