Python 在重复的os.path.isdir调用中出现巨大内存泄漏?
我编写了一些与扫描目录有关的脚本,在调用os.path.isdir时注意到严重的内存泄漏,因此我尝试了以下代码片段:Python 在重复的os.path.isdir调用中出现巨大内存泄漏?,python,memory-leaks,python-2.7,system-calls,Python,Memory Leaks,Python 2.7,System Calls,我编写了一些与扫描目录有关的脚本,在调用os.path.isdir时注意到严重的内存泄漏,因此我尝试了以下代码片段: def func(): if not os.path.isdir('D:\Downloads'): return False while True: func() 几秒钟之内,Python进程就达到了100MB的RAM 我在想到底发生了什么。似乎只有当路径确实是有效的目录路径时(意味着不执行“return False”),巨大的内存泄漏才会生效。
def func():
if not os.path.isdir('D:\Downloads'):
return False
while True:
func()
几秒钟之内,Python进程就达到了100MB的RAM
我在想到底发生了什么。似乎只有当路径确实是有效的目录路径时(意味着不执行“return False”),巨大的内存泄漏才会生效。
另外,查看相关调用(如os.path.isfile)中发生的情况也很有趣
想法
编辑:
我想我发现了什么。
虽然isfile和isdir是在genericpath模块中实现的,但在Windows系统上,isdir是从内置nt导入的。
所以我不得不下载2.7.3的源代码(我早就该下载了…)
经过一点搜索,我在\Modules\posixmodule.c中找到了posix_uuuisdir函数,我假设它是从nt导入的“isdir”函数
这部分功能(和注释)吸引了我的眼球:
if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
attributes = GetFileAttributesW(wpath);
if (attributes == INVALID_FILE_ATTRIBUTES)
Py_RETURN_FALSE;
goto check;
}
/* Drop the argument parsing error as narrow strings
are also valid. */
PyErr_Clear();
似乎这一切都归结为Unicode/ASCII处理错误
我刚刚用unicode中的path参数(即u'D:\Downloads')尝试了上面的代码片段-没有任何内存泄漏。哈哈。根本原因是未能在非Unicode路径中的
路径
变量上调用PyMem\u Free
:
if (!PyArg_ParseTuple(args, "et:_isdir",
Py_FileSystemDefaultEncoding, &path))
return NULL;
attributes = GetFileAttributesA(path);
if (attributes == INVALID_FILE_ATTRIBUTES)
Py_RETURN_FALSE;
check:
if (attributes & FILE_ATTRIBUTE_DIRECTORY)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
根据以下文件:
:与et
相同es
:es
将分配所需大小的缓冲区,将编码数据复制到此缓冲区,并调整*buffer以引用新分配的存储。调用者负责调用PyArg\u ParseTuple()
以在使用后释放分配的缓冲区PyMem\u Free()
这是Python标准库中的一个bug(在Python3中通过直接使用bytes对象修复);将错误报告提交到。Hmm。。。这需要进一步调查。无论目录是否存在,我都会得到内存泄漏。Win7 64位上的Python 2.7.3。做得很好!也许值得向Python bug追踪器报告这一点!干得好!你一定要在bug追踪器上报告!另外,如果您提交一个带有bug报告的补丁(我认为在您的情况下,它只是
PyMem_Free(path)
之后GetFileAttributesA
),那么您可以在ACKS
文件::)中获得您的名字,因此它是函数的ASCII处理部分的一个bug。谢谢,分析到此结束!没错,它在技术上与Unicode/ASCII有关。调整了我的答案,谢谢。很好的分析工作。