Я читаю списки из большого файла, который в итоге хочу сохранить как 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()
.
Кроме того, использование моей собственной версии Pythons int()
с использованием модуля C не приводит к утечке памяти.
Спасибо за вашу помощь!
Edit:
Для проверки модуля я использовал этот скрипт:
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
, но там нет выхода из valgrind между start
и stop
, потому что есть тонны до и после.
Редактировать: Код для подтверждения утечки:
импорт minhashTables
for i in xrange(1000000000):
data = ' '.join(map(str, range(10, 10000)))
foo = minhashTables.ints(data)
Я должен воссоздать строку, потому что strtok меняет ее. Кстати, копирование строки в другую ячейку памяти не меняет поведения.