2011-08-26 151 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