2011-08-26 93 views
1

test.c的:的ctypes和内存泄漏

#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后脚本结束之前?

回答

1

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

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,但只会是正确访问它的问题。我不确定为什么内存不会在你的库中被释放。一般来说,我认为你应该让调用者分配内存并让库初始化它。

而且,它没有完成任何东西来创建一个bts_pointer与m = bts_pointer(),并立即重新分配m到一个新的对象与m = bts_initialize()。您可以删除第一个作业。

编辑:

考虑使用mallopt调整的分配和在堆上和MMAP存储器释放,特别是参数M_TRIM_THRESHOLDM_MMAP_THRESHOLD。默认值可能被优化,以最大限度地减少与调用brk,sbrk等相关的系统调用开销。

0

在Linux系统中,进程决不会只在内存停止时才将内存提供给操作系统。这就是为什么你没有看到内存被释放。

+1

这是不对的。至少,他们主要有能力这样做。如果我'malloc()'一个巨大的部分和'free()'它再次,我的进程的大小缩小。 – glglgl