为什么我的C模块泄漏内存?
我正在从大文件中读取列表,我最终想将其存储为
array.array
s。因为
map(int, line.split())
非常慢,我写了一个小的C模块,它做了strtok和更快版本的atoi:
inline long
minhashTables_myatoi(const char* s)
{
int r;
for (r = 0; *s; r = r * 10 + *s++ - '0');
return r;
}
static PyObject*
minhashTables_ints(PyObject *self, PyObject *args)
{
char* s;
Py_ssize_t slen;
if(!PyArg_ParseTuple(args, "s#", &s, &slen))
return NULL;
long* buf = malloc(sizeof(long) * (slen+1)/2);
const char* tok = strtok(s, " ");
buf[0] = minhashTables_myatoi(tok);
Py_ssize_t i;
for(i = 1; (tok = strtok(NULL, " ")) != NULL; i++)
buf[i] = minhashTables_myatoi(tok);
Py_ssize_t buflen = i;
PyObject* list = PyList_New(buflen);
PyObject *o;
for(i = 0; i < buflen; i++)
{
o = PyInt_FromLong(buf[i]);
PyList_SET_ITEM(list, i, o);
}
free(buf);
return list;
}
所以我的python脚本用字符串调用ints()
并将其传递给array.array
构造函数并将结果数组保存在list
中。
我的问题是,现在脚本泄漏了内存,当然,它没有使用地图而不是ints()
功能。
使用我自己版本的Pythonsint()
使用C模块也不会泄漏内存。
谢谢你的帮助!
编辑:
要使用此脚本对模块进行valgrind:
import minhashTables
data = ' '.join(map(str, range(10)))
print 'start'
foo = minhashTables.ints(data)
del data
del foo
print 'stop'
而且我跑了valgrind --tool=memcheck --leak-check=full --show-reachable=yes python test.py
,但是在start
和stop
之间没有来自valgrind的输出,之前和之后都有吨。
编辑:确认泄漏的代码:
import minhashTables
for i in xrange(1000000000):
data = ' '.join(map(str, range(10, 10000)))
foo = minhashTables.ints(data)
我必须重新创建字符串,因为strtok会更改它。顺便说一下,将字符串复制到另一个内存位置不会改变行为。
没有找到相关结果
已邀请:
3 个回复
仿普
屉杆绊
s,你真的需要
空间吗? 我不熟悉Python / C API,所以这可能是一个糟糕的建议,但是你不能只是迭代字符串并将你找到的每一长时间追加到列表中吗? 即拿这个代码:
然后将
替换为
等一些合适的pythony-goodness。 除了避免
,使用更少的内存并且能够安全地直接在常量Python字符串上操作,此代码还处理诸如空字符串,多个空格和数字之间的其他分隔符等极端情况。 编辑:计算多头 如果你想先计算long的数量,那么你可以分配正确长度的Python List,那么你可以添加如下内容:
哪个应该比较快。 编辑2:更好的解析器 这里是一个稍微好一点的解析器版本,它更紧凑,不需要
而且不必重复代码来处理最终的长:
队辅坟阮阶