为什么内存泄漏?
Why memory leak?
我第一次在clang
中尝试LeakSanitizer
。我将 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak -g")
添加到我的 CMakeLists.txt
.
这是我的 main.cpp
#include <iostream>
#include "linked_queue.h"
int main() {
linked::Char_queue charQueue;
charQueue.enqueue('1');
charQueue.enqueue('2');
charQueue.enqueue('3');
charQueue.enqueue('4');
charQueue.enqueue('5');
charQueue.enqueue('6');
charQueue.enqueue('7');
charQueue.enqueue('8');
while (!charQueue.empty()) {
char temp = charQueue.dequeue();
std::cout << temp << " ";
}
std::cout << std::endl;
return 0;
}
和linked_queue.h
:
#ifndef TEST_LINKED_QUEUE_H
#define TEST_LINKED_QUEUE_H
#include <iostream>
template<class T>
class linked_queue {
public:
linked_queue() : head(Node()), tail(&head) {}
~linked_queue() {
Node *cur = head.next;
while (cur) {
Node *prev = cur;
cur = cur->next;
delete prev;
}
}
[[nodiscard]] bool empty() const { return head.next == nullptr; }
T dequeue() {
T ret = head.next->data;
head.next = head.next->next;
return ret;
}
void enqueue(const T &x) {
tail->next = new Node(x);
tail = tail->next;
}
[[maybe_unused]] [[nodiscard]] bool full() const { return false; }
private:
struct Node {
Node *next;
T data;
explicit Node(const T &data = NULL) : next(nullptr), data(data) {}
};
Node head;
Node *tail;
};
namespace linked {
using Char_queue = linked_queue<char>;
}
#endif //TEST_LINKED_QUEUE_H
当我运行这个的时候,我得到了一个反馈:
=================================================================
==14617==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e48c in main main.cpp:21
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4f0 in main main.cpp:26
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4dc in main main.cpp:25
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4c8 in main main.cpp:24
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4b4 in main main.cpp:23
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4a0 in main main.cpp:22
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e504 in main main.cpp:27
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e518 in main main.cpp:28
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
SUMMARY: LeakSanitizer: 128 byte(s) leaked in 8 allocation(s).
好像是tail->next = new Node(x);
造成了泄漏,但我相信实际上应该不会发生泄漏。你们能帮帮我吗?
因为 enqueue
调用 new
而 dequeue
不调用 delete
,如果你 enqueue
然后 dequeue
,你会泄漏。
您的代码一直有效,直到您从不使用 dequeue
:D。当你调用 dequeue 时,你没有指针指向你的 dequeued Node,然后这个 Node 导致内存泄漏。您必须在函数 dequeue
中删除此节点,或者保存指向此节点的指针并在析构函数中将其删除。我更喜欢第一种方法,因为无论如何你都不需要出列的节点。
我第一次在clang
中尝试LeakSanitizer
。我将 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak -g")
添加到我的 CMakeLists.txt
.
这是我的 main.cpp
#include <iostream>
#include "linked_queue.h"
int main() {
linked::Char_queue charQueue;
charQueue.enqueue('1');
charQueue.enqueue('2');
charQueue.enqueue('3');
charQueue.enqueue('4');
charQueue.enqueue('5');
charQueue.enqueue('6');
charQueue.enqueue('7');
charQueue.enqueue('8');
while (!charQueue.empty()) {
char temp = charQueue.dequeue();
std::cout << temp << " ";
}
std::cout << std::endl;
return 0;
}
和linked_queue.h
:
#ifndef TEST_LINKED_QUEUE_H
#define TEST_LINKED_QUEUE_H
#include <iostream>
template<class T>
class linked_queue {
public:
linked_queue() : head(Node()), tail(&head) {}
~linked_queue() {
Node *cur = head.next;
while (cur) {
Node *prev = cur;
cur = cur->next;
delete prev;
}
}
[[nodiscard]] bool empty() const { return head.next == nullptr; }
T dequeue() {
T ret = head.next->data;
head.next = head.next->next;
return ret;
}
void enqueue(const T &x) {
tail->next = new Node(x);
tail = tail->next;
}
[[maybe_unused]] [[nodiscard]] bool full() const { return false; }
private:
struct Node {
Node *next;
T data;
explicit Node(const T &data = NULL) : next(nullptr), data(data) {}
};
Node head;
Node *tail;
};
namespace linked {
using Char_queue = linked_queue<char>;
}
#endif //TEST_LINKED_QUEUE_H
当我运行这个的时候,我得到了一个反馈:
=================================================================
==14617==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e48c in main main.cpp:21
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4f0 in main main.cpp:26
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4dc in main main.cpp:25
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4c8 in main main.cpp:24
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4b4 in main main.cpp:23
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e4a0 in main main.cpp:22
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e504 in main main.cpp:27
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x100a62778 in wrap__Znwm+0x48 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x6778)
#1 0x10068e778 in linked_queue<char>::enqueue(char const&) linked_queue.h:33
#2 0x10068e518 in main main.cpp:28
#3 0x1836f1f30 in start+0x0 (libdyld.dylib:arm64+0x16f30)
SUMMARY: LeakSanitizer: 128 byte(s) leaked in 8 allocation(s).
好像是tail->next = new Node(x);
造成了泄漏,但我相信实际上应该不会发生泄漏。你们能帮帮我吗?
因为 enqueue
调用 new
而 dequeue
不调用 delete
,如果你 enqueue
然后 dequeue
,你会泄漏。
您的代码一直有效,直到您从不使用 dequeue
:D。当你调用 dequeue 时,你没有指针指向你的 dequeued Node,然后这个 Node 导致内存泄漏。您必须在函数 dequeue
中删除此节点,或者保存指向此节点的指针并在析构函数中将其删除。我更喜欢第一种方法,因为无论如何你都不需要出列的节点。