检查内存泄漏
在这一步骤中,你将学习如何使用 Valgrind 这一强大的内存调试工具来检测和防止 C++ 中的内存泄漏。当动态分配的内存未被正确释放时,就会发生内存泄漏,导致程序消耗越来越多的内存。
首先,在终端中安装 Valgrind:
sudo apt update
sudo apt install -y valgrind
在 WebIDE 中创建一个内存泄漏示例,在 ~/project
目录下创建 memory_leak.cpp
文件:
touch ~/project/memory_leak.cpp
将以下代码添加到 memory_leak.cpp
中:
#include <iostream>
class Resource {
public:
Resource(int value) : data(value) {
std::cout << "Resource created: " << data << std::endl;
}
~Resource() {
std::cout << "Resource destroyed: " << data << std::endl;
}
private:
int data;
};
void createMemoryLeak() {
// 这里会导致内存泄漏,因为资源未被删除
Resource* leak = new Resource(42);
// 缺失:delete leak;
}
int main() {
// 模拟多次内存泄漏
for (int i = 0; i < 3; ++i) {
createMemoryLeak();
}
return 0;
}
使用调试符号编译程序:
g++ -g memory_leak.cpp -o memory_leak
运行 Valgrind 以检测内存泄漏:
valgrind --leak-check=full ./memory_leak
Valgrind 示例输出:
==1988== Memcheck, a memory error detector
==1988== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1988== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1988== Command: ./memory_leak
==1988==
Resource created: 42
Resource created: 42
Resource created: 42
==1988==
==1988== HEAP SUMMARY:
==1988== in use at exit: 12 bytes in 3 blocks
==1988== total heap usage: 5 allocs, 2 frees, 73,740 bytes allocated
==1988==
==1988== 12 bytes in 3 blocks are definitely lost in loss record 1 of 1
==1988== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1988== by 0x109241: createMemoryLeak() (memory_leak.cpp:19)
==1988== by 0x109299: main (memory_leak.cpp:26)
==1988==
==1988== LEAK SUMMARY:
==1988== definitely lost: 12 bytes in 3 blocks
==1988== indirectly lost: 0 bytes in 0 blocks
==1988== possibly lost: 0 bytes in 0 blocks
==1988== still reachable: 0 bytes in 0 blocks
==1988== suppressed: 0 bytes in 0 blocks
==1988==
==1988== For lists of detected and suppressed errors, rerun with: -s
==1988== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
如你所见,Valgrind 检测到 12 字节的内存泄漏,分布在 3 个块中。createMemoryLeak()
中创建的 Resource
对象未被删除,导致了内存泄漏。
要修复内存泄漏,修改代码以正确删除资源:
void createMemoryLeak() {
// 正确删除动态分配的资源
Resource* leak = new Resource(42);
delete leak; // 添加此行以防止内存泄漏
}
重新编译并使用 Valgrind 运行程序,以验证内存泄漏已修复:
g++ -g memory_leak.cpp -o memory_leak
valgrind --leak-check=full ./memory_leak
==2347== Memcheck, a memory error detector
==2347== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2347== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==2347== Command: ./memory_leak
==2347==
Resource created: 42
Resource destroyed: 42
Resource created: 42
Resource destroyed: 42
Resource created: 42
Resource destroyed: 42
==2347==
==2347== HEAP SUMMARY:
==2347== in use at exit: 0 bytes in 0 blocks
==2347== total heap usage: 5 allocs, 5 frees, 73,740 bytes allocated
==2347==
==2347== All heap blocks were freed -- no leaks are possible
==2347==
==2347== For lists of detected and suppressed errors, rerun with: -s
==2347== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
关于内存泄漏的关键点:
- 始终
delete
动态分配的内存
- 使用智能指针如
unique_ptr
和 shared_ptr
- 使用 Valgrind 检测内存泄漏
- 使用
-g
标志编译以获得更好的调试信息