大小为 8 的 Valgrind 无效读取和地址 0x5b7e520 是大小为 16 的块内的 0 字节 free'd
Valgrind Invalid read of size 8 and Address 0x5b7e520 is 0 bytes inside a block of size 16 free'd
我已经阅读了几个有类似错误的问题,但我无法弄清楚我的问题。我已经检查过删除后我没有访问任何东西,或者尝试删除它两次。
class节点和列表是我自己实现的,但我在这之前的几次练习中都用过,所以我认为问题不在class实现上。这是代码和 valgrind 给出的错误。顺便说一句,该程序显然有效。
==10365== Invalid read of size 8
==10365== at 0x10992A: Node::getNext() const (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x1099F2: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF5C: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e520 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE24: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD8E: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365== Invalid free() / delete / delete[] / realloc()
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF5C: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e520 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE24: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD8E: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365== Invalid read of size 8
==10365== at 0x10992A: Node::getNext() const (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x1099F2: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF6B: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e430 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE15: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD52: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365== Invalid free() / delete / delete[] / realloc()
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF6B: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e430 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE15: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD52: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365==
==10365== HEAP SUMMARY:
==10365== in use at exit: 0 bytes in 0 blocks
==10365== total heap usage: 31 allocs, 38 frees, 74,736 bytes allocated
==10365==
==10365== All heap blocks were freed -- no leaks are possible
==10365==
==10365== For counts of detected and suppressed errors, rerun with: -v
==10365== ERROR SUMMARY: 14 errors from 4 contexts (suppressed: 0 from 0)
这是代码:
int getNodeSum(Node * head1, Node * head2, List & sumList) {
int sum = 0;
int digit1 = 0;
int digit2 = 0;
digit1 = head1->getData();
head1 = head1->getNext();
digit2 = head2->getData();
head2 = head2->getNext();
int carry = 0;
if(head1 != 0 && head2 != 0)
carry = getNodeSum(head1, head2, sumList);
sum = digit1 + digit2 + carry;
carry = floor(sum / 10);
sum = sum % 10;
sumList.append(sum);
return carry;
}
List sumNotReverse(List l1, List l2) {
List mySum;
//First we need to pad the lists
int length1 = l1.length();
int length2 = l2.length();
int diff = length1-length2;
if(diff < 0) {
//Then we need to pad list 1
diff = abs(diff);
for(int i = 0; i < diff; i++) {
Node * pad = new Node();
pad->setNext(l1.getHead());
l1.setHead(pad);
}
} else if(diff > 0 ) {
for(int i = 0; i < diff; i++) {
Node * pad = new Node();
pad->setNext(l2.getHead());
l2.setHead(pad);
}
}
int carry = getNodeSum(l1.getHead(), l2.getHead(), mySum);
if(carry == 1)
mySum.append(carry);
//Now we have to reverse the list. There are more/different efficient ways to implement this
stack<int> digits;
Node * aux = mySum.getHead();
Node * prev = aux;
while(aux != 0) {
digits.push(aux->getData());
//Doing this makes space complexity O(N) instead of O(2N)
//(the other way is cleaning the list when we are done)
prev = aux;
aux = aux->getNext();
delete prev;
}
//Make sure head is null
mySum.setHead(0);
while(digits.size() > 0) {
mySum.append(digits.top());
digits.pop();
}
return mySum;
}
我可以解释代码的作用,但有些人认为这些信息毫无用处,所以如果您需要,请告诉我。
请愿,这里是 Node::getNext(), List::clean() 和 List::~List()
的代码
Node * Node::getNext() const {
return next;
}
List::~List() {
clean();
}
void List::clean() {
if(list != 0) {
Node* aux;
while(list != 0) {
aux = list->getNext();
delete list;
list = aux;
}
}
}
这是查看属性的 .h:
class Node {
private:
Node * next;
int data;
public:
Node();
int getData() const;
Node * getNext() const;
void setData(int data);
void setNext(Node * next);
};
class List {
private:
Node * list;
public:
List();
~List();
void clean();
int length() const;
Node * getHead() const;
void setHead(Node * head);
// Insert a node at the end of the list with data given by the argument
void append(int value);
void print() const;
void remove(int pos);
//Remove node toDelete given the reference and the reference to the previous one
//Then, this remove is O(1) time complexity
void remove(Node * prev, Node * toDelete);
void removeDuplicates();
void removeDuplicatesnoBuffer();
};
您可以下载完整代码进行编译here。在main()中,第136行和164行之间没有用,可以忽略。这是练习的另一部分。
您的 List
class 缺少有效的复制构造函数和赋值运算符,但您正在复制 List
对象,例如当您调用 sumNotReverse
.
这将导致双重释放或释放后使用,这可能是 valgrind 抱怨的问题。
有关详细信息,请参阅此处 What is The Rule of Three?,或查阅您最喜欢的 C++ 书籍。任何体面的 C++ 书籍都会涵盖这个主题。
我已经阅读了几个有类似错误的问题,但我无法弄清楚我的问题。我已经检查过删除后我没有访问任何东西,或者尝试删除它两次。
class节点和列表是我自己实现的,但我在这之前的几次练习中都用过,所以我认为问题不在class实现上。这是代码和 valgrind 给出的错误。顺便说一句,该程序显然有效。
==10365== Invalid read of size 8
==10365== at 0x10992A: Node::getNext() const (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x1099F2: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF5C: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e520 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE24: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD8E: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365== Invalid free() / delete / delete[] / realloc()
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF5C: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e520 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE24: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD8E: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365== Invalid read of size 8
==10365== at 0x10992A: Node::getNext() const (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x1099F2: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF6B: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e430 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE15: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD52: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365== Invalid free() / delete / delete[] / realloc()
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BF6B: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Address 0x5b7e430 is 0 bytes inside a block of size 16 free'd
==10365== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109A0A: List::clean() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10998F: List::~List() (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BE15: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== Block was alloc'd at
==10365== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10365== by 0x109AA3: List::append(int) (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365== by 0x10BD52: main (in /mnt/HDD 1TB/TFG/Cracking the code/Chapter 2/prueba)
==10365==
==10365==
==10365== HEAP SUMMARY:
==10365== in use at exit: 0 bytes in 0 blocks
==10365== total heap usage: 31 allocs, 38 frees, 74,736 bytes allocated
==10365==
==10365== All heap blocks were freed -- no leaks are possible
==10365==
==10365== For counts of detected and suppressed errors, rerun with: -v
==10365== ERROR SUMMARY: 14 errors from 4 contexts (suppressed: 0 from 0)
这是代码:
int getNodeSum(Node * head1, Node * head2, List & sumList) {
int sum = 0;
int digit1 = 0;
int digit2 = 0;
digit1 = head1->getData();
head1 = head1->getNext();
digit2 = head2->getData();
head2 = head2->getNext();
int carry = 0;
if(head1 != 0 && head2 != 0)
carry = getNodeSum(head1, head2, sumList);
sum = digit1 + digit2 + carry;
carry = floor(sum / 10);
sum = sum % 10;
sumList.append(sum);
return carry;
}
List sumNotReverse(List l1, List l2) {
List mySum;
//First we need to pad the lists
int length1 = l1.length();
int length2 = l2.length();
int diff = length1-length2;
if(diff < 0) {
//Then we need to pad list 1
diff = abs(diff);
for(int i = 0; i < diff; i++) {
Node * pad = new Node();
pad->setNext(l1.getHead());
l1.setHead(pad);
}
} else if(diff > 0 ) {
for(int i = 0; i < diff; i++) {
Node * pad = new Node();
pad->setNext(l2.getHead());
l2.setHead(pad);
}
}
int carry = getNodeSum(l1.getHead(), l2.getHead(), mySum);
if(carry == 1)
mySum.append(carry);
//Now we have to reverse the list. There are more/different efficient ways to implement this
stack<int> digits;
Node * aux = mySum.getHead();
Node * prev = aux;
while(aux != 0) {
digits.push(aux->getData());
//Doing this makes space complexity O(N) instead of O(2N)
//(the other way is cleaning the list when we are done)
prev = aux;
aux = aux->getNext();
delete prev;
}
//Make sure head is null
mySum.setHead(0);
while(digits.size() > 0) {
mySum.append(digits.top());
digits.pop();
}
return mySum;
}
我可以解释代码的作用,但有些人认为这些信息毫无用处,所以如果您需要,请告诉我。
请愿,这里是 Node::getNext(), List::clean() 和 List::~List()
的代码Node * Node::getNext() const {
return next;
}
List::~List() {
clean();
}
void List::clean() {
if(list != 0) {
Node* aux;
while(list != 0) {
aux = list->getNext();
delete list;
list = aux;
}
}
}
这是查看属性的 .h:
class Node {
private:
Node * next;
int data;
public:
Node();
int getData() const;
Node * getNext() const;
void setData(int data);
void setNext(Node * next);
};
class List {
private:
Node * list;
public:
List();
~List();
void clean();
int length() const;
Node * getHead() const;
void setHead(Node * head);
// Insert a node at the end of the list with data given by the argument
void append(int value);
void print() const;
void remove(int pos);
//Remove node toDelete given the reference and the reference to the previous one
//Then, this remove is O(1) time complexity
void remove(Node * prev, Node * toDelete);
void removeDuplicates();
void removeDuplicatesnoBuffer();
};
您可以下载完整代码进行编译here。在main()中,第136行和164行之间没有用,可以忽略。这是练习的另一部分。
您的 List
class 缺少有效的复制构造函数和赋值运算符,但您正在复制 List
对象,例如当您调用 sumNotReverse
.
这将导致双重释放或释放后使用,这可能是 valgrind 抱怨的问题。
有关详细信息,请参阅此处 What is The Rule of Three?,或查阅您最喜欢的 C++ 书籍。任何体面的 C++ 书籍都会涵盖这个主题。