使用Valgrind调试Python CFFI扩展时无法检测内存泄漏
补全Python环境变量配置
仅设置PYTHONMALLOC=malloc不足以绕开Python 3.11自带的内存池和缓存,得额外添加两个变量强制使用系统malloc:PYTHONMALLOC=malloc PYTHONMALLOCSTATS=1 PYTHONDEVMODE=1 valgrind --leak-check=full --show-leak-kinds=all python your_test_script.pyPYTHONDEVMODE=1会禁用内存池,PYTHONMALLOCSTATS可以帮你确认内存分配器确实切换成了系统malloc。调整Valgrind的过滤规则
Python本身启动和退出时会有正常的残留内存,Valgrind默认会过滤这些,但可能误过滤你的扩展泄漏。启动时指定Python官方抑制文件:valgrind --suppressions=/usr/lib/python3.11/config-3.11-x86_64-linux-gnu/python.supp --leak-check=full ...路径根据你的系统和Python版本调整,找不到可以用
find /usr -name "python.supp"搜索。另外加上--trace-children=yes,防止漏检子进程的泄漏。确认C层内存分配方式
要保证扩展里的泄漏内存是用malloc/calloc直接分配的,如果用了PyMem_Malloc这类Python提供的分配函数,Python内存管理器会接管,Valgrind不会标记为泄漏。另外,如果你用了CFFI的ffi.gc绑定自动回收,那忘调用释放函数也不会产生泄漏——得确认测试用例确实是完全没触发回收的场景。用极简测试脚本排除干扰
写个最干净的测试脚本,只做创建泄漏对象这一件事:from your_cffi_ext import create_leaking_handle handle = create_leaking_handle() # 直接退出,不做其他操作用这个脚本跑Valgrind,避免其他Python代码的内存操作干扰检测结果。
升级Valgrind版本
Valgrind 3.18.1对Python 3.11的支持不算完善,新版本(比如3.22及以上)修复了不少和Python 3.10+内存机制兼容的问题,升级后大概率能解决检测不到的问题。
内容的提问来源于stack exchange,提问作者Slav

