ctypes和内存泄漏

时间:2011-08-26 21:58:31

标签: python ctypes

test.c的:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXFRAGMENTS 4000000

typedef struct {
    uint64_t FirstFragmentTimestamp;
} fragment_t;

typedef struct {
    fragment_t** fragments;
} bts_t;


bts_t* initialize() {
    uint32_t i;
    bts_t* bts;
    bts = (bts_t *) malloc(sizeof(bts_t));
    bts->fragments= (fragment_t **) malloc(sizeof(bts_t *)*MAXFRAGMENTS);
    for(i=0;i<MAXFRAGMENTS;i++) {
        (bts->fragments)[i]=(fragment_t *) malloc(sizeof(fragment_t));
        (bts->fragments)[i]->FirstFragmentTimestamp = 0;
    }
    return bts;
}

int fr(bts_t *bts)
{
    uint32_t i;
    if ( bts != NULL ) {
        for(i=0;i<MAXFRAGMENTS;i++) {
            free(bts -> fragments[i]);
        }
        free(bts->fragments);
    }
    free(bts);
  return 1;
}


int main() {
}

test.py:

from ctypes import *
import time

class fragment(Structure):
    _fields_=[("FirstFragmentTimestamp",c_ulong)]

class bts(Structure):
    _fields_=[("fragments",POINTER(POINTER(fragment)))]


bts_pointer=POINTER(bts)
bts_library=CDLL("test.so")
bts_initialize = bts_library.initialize
bts_initialize.restype = bts_pointer
bts_free = bts_library.fr
m = bts_pointer()
m = bts_initialize()
bts_free(m)
print 'done'
time.sleep(20)

为什么顶级显示,在运行bts_free之后和脚本结束之前哪些内存不是免费的?

3 个答案:

答案 0 :(得分:1)

这可能不是您唯一的问题,但是ctypes类型c_ulong对应于C类型unsigned long,它只有32位。您应该使用c_ulonglong代替,这是64位。

答案 1 :(得分:1)

适用于Windows(gcc 4.5.3):

import os
m = bts_initialize()
os.system('tasklist /fi "imagename eq python.exe"')
bts_free(m)
os.system('tasklist /fi "imagename eq python.exe"')

输出:

Image Name                   PID Session Name     Session#    Mem Usage
========================= ====== ================ ======== ============
python.exe                  3784                         0     84,440 K

Image Name                   PID Session Name     Session#    Mem Usage
========================= ====== ================ ======== ============
python.exe                  3784                         0      6,356 K

正如亚当罗森菲尔德所说,你的结构应该有一个ctypes.c_ulonglong,但这只会是正确访问它的问题。我不确定为什么你的库里没有释放内存。但是,一般情况下,我认为应该让调用者分配内存并让库初始化它。

此外,使用m = bts_pointer()创建bts_pointer并立即将m重新分配给m = bts_initialize()的新对象并未完成任何操作。您可以删除第一个作业。

编辑:

使用mallopt调整堆和mmap上的内存分配和释放,特别是参数M_TRIM_THRESHOLDM_MMAP_THRESHOLD。默认值可能已经过优化,以最大限度地减少与调用brksbrk等相关的系统调用开销。

答案 2 :(得分:0)

在Linux系统中,进程永远不会将内存返回给操作系统,只有当它们停止时。这就是为什么你看不到释放内存的原因。