Bdfy
Bdfy

Reputation: 24621

ctypes and memory leak

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)

Why top show, what memory not free after run bts_free and before end of script ?

Upvotes: 1

Views: 1203

Answers (3)

Eryk Sun
Eryk Sun

Reputation: 34260

It works on 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"')

Output:

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

As Adam Rosenfield said, your Structure should have a ctypes.c_ulonglong, but that will only be a problem with accessing it correctly. I'm not certain why the memory isn't being freed in your library. In general, though, I think you should let the caller allocate the memory and have the library initialize it.

Also, it's not accomplishing anything to create a bts_pointer with m = bts_pointer() and immediately reassign m to a new object with m = bts_initialize(). You can delete the first assignment.

Edit:

Look into using mallopt to tune the allocation and release of memory on the heap and mmap, specifically the parameters M_TRIM_THRESHOLD and M_MMAP_THRESHOLD. The default values are probably optimized to minimize system call overhead associated with calling brk, sbrk, etc.

Upvotes: 1

daniel kullmann
daniel kullmann

Reputation: 14013

In Linux systems, processes never give memory back to the OS, only when they stop. This is why you don't see the memory being released.

Upvotes: 0

Adam Rosenfield
Adam Rosenfield

Reputation: 400204

This may not be your only problem, but the ctypes type c_ulong corresponds to the C type unsigned long, which is only 32 bits. You should use c_ulonglong instead, which is 64 bits.

Upvotes: 1

Related Questions