2016-05-05 5 views
2

Я пытаюсь исправить утечку памяти в оболочке Python для dll C++. Проблема заключается в том, назначая буфер байтов вспомогательный объект, который был создан в Python:Освобождение памяти от карты SWIG-карты

struct ByteBuffer 
{ 
    int length; 
    uint8_t * dataBuf;  
}; 

Я хочу, чтобы поставить dataBuf как массив Python, поэтому TypeMap, что я придумал (и работает) в том, что:

%module(directors="1") mymodule 

%typemap(in) uint8_t * (uint8_t *temp){ 
    int length = PySequence_Length($input); 
    temp = new uint8_t[length]; // memory allocated here. How to free? 
    for(int i=0; i<length; i++) { 
     PyObject *o = PySequence_GetItem($input,i); 
     if (PyNumber_Check(o)) { 
      temp[i] = (uint8_t) PyLong_AsLong(o); 
      //cout << (int)temp[i] << endl; 
     } else { 
      PyErr_SetString(PyExc_ValueError,"Sequence elements must be uint8_t");  
      return NULL; 
     } 
    } 
    $1 = temp; 
} 

проблема состоит в том, что TypeMap выделяет память для нового массива C каждый раз, и эта память не освобождается в библиотеке DLL. Другими словами, dll ожидает, что пользователь будет управлять памятью DataBuf ByteBuffer. Например, при создании 10000 таких объектов последовательно в Python, а затем удалить их, то повышается использование памяти устойчиво (утечка):

for i in range(10000): 
    byteBuffer = mymodule.ByteBuffer() 
    byteBuffer.length = 10000 
    byteBuffer.dataBuf = [0]*10000 
    # ... use byteBuffer 
    del byteBuffer 

Есть ли способ, чтобы удалить выделенную dataBuf из питона? Спасибо за ваше терпение!

Редактировать: Я не размещаю весь рабочий код, чтобы он был коротким. Если потребуется, я сделаю это. Кроме того, я использую Python 3.5 x64 и SWIG ver 3.0.7

+0

Ваш пример настолько близок к тому, чтобы быть минимальным полным примером того, что вы могли бы сделать его одним. Вы можете использовать ℅inline для добавления определения структуры в файл .I. – Flexo

ответ

0

Это было намного проще, чем я думал. Я просто добавил это к файлу .i

%typemap(freearg) uint8_t * { 
    //cout << "Freeing uint8_t*!!! " << endl; 
    if ($1) delete[]($1); 
} 

Кажется, что нужно работать. Редактировать: отключено с удалением []

+0

, вы выделили 'new []', поэтому вам следует освободить с помощью 'delete []', чтобы избежать неопределенного поведения. Проверка null является излишней. – Flexo

+0

@Flexo, похоже, с удалением [] тоже. Не уверен, почему free() создает неопределенное поведение. –

+0

Не имеет значения, работает ли оно или нет, это неправильно. http://stackoverflow.com/questions/1612031/is-there-any-danger-in-calling-free-or-delete-instead-of-delete – Flexo

Смежные вопросы