Python: ошибка ctypes C malloc. Проблема с памятью C или проблема с Python / ctypes?

#python #c #malloc #ctypes

#python #c #malloc #ctypes

Вопрос:

все. У меня ошибка выделения памяти с использованием ctypes и кода C. Мне интересно, является ли проблема с памятью внутри C или вызвана неправильным использованием ctypes. Ошибка памяти

python (79698) malloc: * ошибка для объекта 0x15627ac08: неправильная контрольная сумма для освобожденного объекта >- объект, вероятно, был изменен после освобождения. установите точку останова в malloc_error_break для прерывания отладки

или

python(76110,0x7fff70062ca0) malloc: * ошибка для объекта 0x7d807e1078907df: указатель > освобожден, не был выделен * установите точку останова в malloc_error_break для прерывания отладки

в зависимости от того, как я напишу «free_some_memory» часть кода ниже. Я не буду публиковать здесь кучу кода на C, но предполагая, что я написал код на C правильно, правильно ли выглядит мой интерфейс ctypes?

Кроме того, сбои, с которыми я сталкиваюсь, не всегда происходят в одном и том же месте в моих скриптах для данной версии «free_some_memory». Возможно ли, что мое управление памятью в коде C написано плохо, так что управление памятью в Python может или не может привести к неправильному распределению (де) ресурсов?

Не знаю, важно ли это, но я работаю на Mac, Snow Leopard.
Любая помощь, которую вы можете предложить, была бы очень признательна.

Лучший, jkmacc

Мой код на C выглядит так:

 /**** cfunction.c ****/
int cfun (double *y, char datafile[1024], int byteoffset, int num )
{
  allocate_some_memory;
  do_stuff;

  if ( error_condition )
  {
    free_some_memory;
    return ( -1 );
  }

  fill_y_here;
  free_some_memory;
  return ( 0 );
}
  

Моя оболочка ctypes выглядит следующим образом:

 #pyfunction.py

import ctypes as C
import numpy as np

lib = C.CDLL('mylib.dylib')

def pyfun(DATAFILE, BYTEOFFSET, NUM):
    """
    DATAFILE: a string file name
    BYTEOFFSET: an integer
    NUM: an integer
    """

    #return integer success/failure flag
    lib.cfun.restype = C.c_int 

    #array memory to be filled inside of C
    Y = np.empty(NUM,dtype='double',order='C')

    cDATAFILE = C.create_string_buffer(DATAFILE,1024) 
    cBYTEOFFSET = C.c_int(int(BYTEOFFSET))
    cNUM = C.c_int(int(NUM))

    flag = lib.cfun(Y.ctypes.data_as(C.POINTER(C.c_double)),  
               cDATAFILE,cBYTEOFFSET,cNUM)

    if flag == -1:
        print("Something went wrong.")
        return -1
    else:
        return Y
  

Комментарии:

1. Вам нужно опубликовать фактический код для cfunction.c, а не псевдокод.

2. Код на Python в порядке. Опубликуйте код на C. Обратите внимание, что вы можете передавать строки, целые числа, указатели непосредственно на функции C, не помещая их в типы ctypes (передавать DATAFILE, BYTEOFFSET, NUM напрямую без cDATAFILE и т.д. переводов.

3. Спасибо, что просмотрели это. Я приведу минимальный пример C, который порождает проблему, поскольку я не могу опубликовать полный код.

4. Я получаю ту же проблему, используя библиотеку Python GDLA в OS X с установленным brew gdal и установленным pip gdal 1.10.1 / 1.10.0 Есть идеи?

Ответ №1:

У меня была эта проблема, и вот что я выяснил:

Если вы сопоставите что-либо с ctypes, а затем освободите это, вы получите сообщение об ошибке, когда объект ctypes будет уничтожен. Итак, прежде чем вызывать free(), вам нужно убедиться, что в коде python не осталось ссылок на него.

Итак, ваш код на C будет выглядеть:

 char* p;
char* allocate() {
 p = asprintf("hello world");
 return(p)
}
void freep() {
 free(p);
}
  

И ваш код на Python будет выглядеть:

 allocate = clib.allocate
allocate.restype = c_char_p()
p = allocate()
print p
# This is the key:
del(p)
clib.freep()
  

Если вы хотите увидеть ошибку, просто опустите del(p)