为什么我的C模块内存泄漏?

2024-09-29 19:04:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在从一个大文件中读取列表,我最终希望将其存储为array.arrays

map(int, line.split())

非常慢,我编写了一个小型C模块来执行strtok和一个更快的atoi版本:

^{pr2}$

因此,我的python脚本使用一个字符串调用ints(),并将其传递给array.array构造函数,并将结果数组保存在list中。在

我的问题是,现在脚本泄漏了内存,当然,它没有使用map而不是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和{}之间没有valgrind的输出,前后有吨。在

编辑:确认泄漏的代码: 导入minhashTables

for i in xrange(1000000000):
    data = ' '.join(map(str, range(10, 10000)))
    foo = minhashTables.ints(data)

我必须重新创建字符串,因为strtok改变了它。顺便说一下,将字符串复制到另一个内存位置不会改变行为。在


Tags: 模块内存字符串版本脚本编辑mapdata
3条回答

试试这个

inline long
    minhashTables_myatoi(const char* s)
    {
        long result=0;
        while((*s)!='\0'){
            result = result * 10 + (*s- '0');
            s++;
        }
        return result;
    }

我建议您看看Valgrind-这是一个非常有用的工具,可以帮助您了解C语言中内存泄漏的问题

你真的需要为所有这些long关闭空间吗?在

我不熟悉Python/capi,所以这可能是一个糟糕的建议,但是您不能在字符串上迭代并在执行时将找到的每个long追加到列表中吗?在

也就是说,取这个代码:

static const char* const testString = "12 345  67  8 910 11 1213 141516, 1718";

int main()
{
    const char* i = testString;
    long parseLong = 0;
    int gotLong = 0;

    for (;*i;++i)
    {
        if ('0' <= *i && *i <= '9')
        {
            parseLong = (parseLong * 10) + (*i - '0');
            gotLong = 1;
        }
        else if (gotLong)
        {
            printf("Got: %d\n", parseLong);
            parseLong = 0;
            gotLong = 0;
        }
    }

    if (gotLong)
        printf("Got: %d\n", parseLong);
}

然后将printf替换为一些合适的Python善性,比如PyList_Append()。在

除了避免malloc,使用更少的内存,并且能够安全地直接对常量Python字符串进行操作,此代码还可以处理诸如空字符串、多个空格和数字之间的其他分隔符之类的转角情况。在


编辑:计算多头数 如果您想先计算long的数量,这样就可以分配正确长度的Python List,那么您只需添加如下内容: ^{pr2}$

应该比较快。


编辑2:更好的解析器
上面的解析器有一个稍微好一点的版本,它更紧凑,不需要gotLong,也不必重复代码来处理最后的long:
    for (i = testString;*i;++i)
    {
        if (isdigit(*i))
        {
            do {
                parseLong = (parseLong * 10) + (*i - '0');
            } while (*++i && isdigit(*i));

            printf("Got: %d\n", parseLong);
            parseLong = 0;
        }
    }   

相关问题 更多 >

    热门问题