如何在 python 中使用 valgrind?

Posted

技术标签:

【中文标题】如何在 python 中使用 valgrind?【英文标题】:How to use valgrind with python? 【发布时间】:2013-12-05 10:50:52 【问题描述】:

我正在尝试 memcheck 我正在编写的 C python 扩展,但我在设置 valgrind 以使用 python 时遇到问题。我真的很感激一些建议。就上下文而言,这是 Ubuntu 13.10、python 2.7.5+ 和 valgrind 3.8.1。

根据Readme.valgrind 的建议,我做了以下事情。

1) 用

下载了python源码
sudo apt-get build-dep python2.7
apt-get source python2.7

2) 应用代码补丁,即“取消注释 Objects/obmalloc.c 中的 Py_USING_MEMORY_DEBUGGER”。

3) 应用了抑制补丁,即“取消注释 Misc/valgrind-python.supp 中抑制 PyObject_Free 和 PyObject_Realloc 警告的行”

4) 用

编译的python
./configure --prefix=/home/dejan/workspace/python --without-pymalloc
make -j4 install

请注意,我同时执行了 2 和 3,而 README.valgrind 说要执行 2 或 3... 更多也无妨。

现在,让我们在 test.py 中的一些示例 python 代码上进行测试

print "Test"

让我们用这个脚本在 python 上运行 valgrind

valgrind --tool=memcheck --leak-check=full --suppressions=python2.7-2.7.5/Misc/valgrind-python.supp bin/python test.py

出乎意料的是,仍然有大量来自 valgrind 的报告,其中第一个是(以及更多后续)

==27944== HEAP SUMMARY:
==27944==     in use at exit: 857,932 bytes in 5,144 blocks  
==27944==   total heap usage: 22,766 allocs, 17,622 frees, 4,276,934 bytes allocated
==27944== 
==27944== 38 bytes in 1 blocks are possibly lost in loss record 24 of 1,343
==27944==    at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27944==    by 0x46B8DD: PyString_FromString (stringobject.c:143)
==27944==    by 0x439631: PyFile_FromFile (fileobject.c:157)
==27944==    by 0x4E9B4A: _PySys_Init (sysmodule.c:1383)
==27944==    by 0x4E29E9: Py_InitializeEx (pythonrun.c:222)
==27944==    by 0x4154B4: Py_Main (main.c:546)
==27944==    by 0x577DDE4: (below main) (libc-start.c:260)

我做错了吗?有没有办法对不泄漏的python脚本进行valgrind并获得干净的valgrind输出?

【问题讨论】:

你见过***.com/questions/1519276/… @VooDooNOFX 我已经搜索了 *** 及其他内容,所有答案基本上都说我应该做我所描述的事情——编译 python 或使用抑制。这确实摆脱了自定义分配问题报告,例如 PyObject_Free (这是您链接的问题中的报告),但我得到的报告不是那种。 为了测试我的 c 扩展,我使用答案中提供的说明编译了调试 python。我用调试版python重建了我的扩展,结果失败了。我使用 setuptools 扩展构建了扩展,它在系统环境下运行良好。构建标志非常不同。 【参考方案1】:

我找到了答案here。

Python也需要在调试模式下编译,即

./configure --prefix=/home/dejan/workspace/python --without-pymalloc --with-pydebug --with-valgrind

此外,numpy 有一个 suppresion file 可以消除额外的 valgrind 警告。

【讨论】:

感谢大家为大家做研究!你知道是否应该在使用 valgrind 完成后重新编译 python?而且,更重要的是 - 怎么做? 对我有用的是编译/安装与 valgrind 兼容的 python 版本,然后基于 virtualenv。这给了我方便的activate 脚本。 virtualenvwrapper 会更好 这是否会使每个 python 命令调用都使用 valgrind 运行?我注意到使用 pip 安装软件包的速度明显变慢 @JamesRobertAlbert 来自自述文件:注意:配置 python --without-pymalloc 会使 Python 运行速度变慢,尤其是在 Valgrind 下运行时。 ...运行 --without-pymalloc 似乎需要大约 5 倍的时间 @YairDaon 你不必重新编译 Python,因为你创建了一个新的解释器。相关:***.com/questions/36697863/….【参考方案2】:

从 python 3.6 开始,有一个 PYTHONMALLOC 环境变量可在发布版本中使用,无需重新编译。

PYTHONMALLOC=malloc python3 foobar.py

这将禁用 pymalloc 并直接使用 libc malloc,使其对 valgrind 友好。这相当于--without-pymalloc(同样慢)

如果 valgrind 太慢,其他值可能会有所帮助。 PYTHONMALLOC=debugPYTHONMALLOC=malloc_debug 分别在默认分配器和 libc 分配器之上添加调试钩子。它们的效果,来自文档:

新分配的内存被字节 0xCB 填充 释放的内存被字节 0xDB 填充 检测 Python 内存分配器 API 的违规行为。例如,在 PyMem_Malloc() 分配的内存块上调用 PyObject_Free()。 在缓冲区开始之前检测写入(缓冲区下溢) 在缓冲区结束后检测写入(缓冲区溢出) 当调用 PYMEM_DOMAIN_OBJ(例如:PyObject_Malloc())和 PYMEM_DOMAIN_MEM(例如:PyMem_Malloc())域的分配器函数时,检查 GIL 是否被保留。

这将捕获一些未初始化的读取、一些在释放后使用、一些缓冲区不足/溢出等,但不会报告泄漏并且不会触及未通过 python 分配的内存(使用 glibc 时,@987654329 @ 和 MALLOC_CHECK_ 环境变量可能会有所帮助)

另见:

Details of the available values 3.6 release notes 附使用说明 Current location of README.valgrind

【讨论】:

以上是关于如何在 python 中使用 valgrind?的主要内容,如果未能解决你的问题,请参考以下文章

如何在基于 Qt 的应用程序中正确使用 valgrind

使用 Valgrind 在 Python 程序中分析内存时遇到问题

如何修复 Valgrind 日志中的内存泄漏

如何在 Linux (redhat) 上通过 gdb 在 xterm 中使用 valgrind?

如何使用 valgrind 查找内存泄漏?

如何抑制来自 gpgme 的 valgrind 警告?