主要观点:作者花费一周时间寻找 Postgres 的 WAL Sender 进程中的内存泄漏,尝试 Valgrind 和 gcc/clang sanitizers 无果后,偶然发现 bcc 工具集中的 memleak 程序找到了泄漏源。文中详细介绍了 Valgrind、Postgres 中的内存管理(MemoryContext)、设置 Valgrind 包装器、AddressSanitizer 和 LeakSanitizer 以及 eBPF 和 bcc 工具等用于检测内存泄漏的方法和过程。
关键信息:
- 在 Postgres 的
PostgresMain()
函数中添加循环分配内存导致内存泄漏,每次连接客户端发送语句就会分配新的 4KB 块。 - Valgrind 主要在程序结束时检查泄漏,对 Postgres 中的内存泄漏检测效果不佳,且使用 --leak-check=full 标志时 Postgres 会崩溃。
- AddressSanitizer 和 LeakSanitizer 可直接集成到
clang
和gcc
中,通过-fsanitize=address
编译代码启用,但默认行为是在遇到第一个错误时崩溃,可通过设置环境变量ASAN_OPTIONS="halt_on_error=false"
让其继续运行。 - eBPF 和 bcc 工具中的 memleak 程序可用于记录运行程序的内存使用情况和分配来源,通过
sudo /usr/share/bcc/tools/memleak -p [PID]
运行,能准确找到内存泄漏位置及堆栈跟踪。
重要细节: - 展示了简单
main.c
程序在使用和不使用free(x)
时 Valgrind 的检测结果。 - 介绍了 Postgres 的安装、配置和启动过程,以及在其中引入内存泄漏的方法。
- 给出了 Valgrind 包装器脚本的内容和使用方法,以及 Postgres 与各种工具结合检测内存泄漏的具体步骤和输出。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。