Who owns the memory in ctypes?

eryk sun eryksun at gmail.com
Tue Nov 15 00:19:46 EST 2016


On Tue, Nov 15, 2016 at 3:15 AM, Cem Karan <cfkaran2 at gmail.com> wrote:
> if my C code allocates memory via GC_MALLOC() (the standard call for allocating memory
> in the garbage collector), and I access some object via ctypes in python, will the python
> garbage collector assume that it owns it and attempt to dispose of it when it goes out of
> scope?

ctypes objects own only the memory that they allocate. Inspect the
_b_needsfree_ attribute to determine whether a ctypes object owns the
referenced memory.

For example:

This array object owns a 12-byte buffer for the array elements:

    >>> arr = (ctypes.c_uint * 3)(0, 1, 2)
    >>> arr._b_needsfree_
    1

This pointer object owns an 8-byte buffer for the 64-bit target address:

    >>> p = ctypes.POINTER(ctypes.c_uint * 3)(arr)
    >>> p._b_needsfree_
    1

The following new array object created by dereferencing the pointer
does not own the 12-byte buffer:

    >>> ref = p[0]
    >>> ref[:]
    [0, 1, 2]
    >>> ref._b_needsfree_
    0

However, it does have a reference chain back to the original array:

    >>> ref._b_base_ is p
    True
    >>> p._objects['1'] is arr
    True

On the other hand, if you use the from_address() class method, the
resulting object is a dangling reference to memory that it doesn't own
and for which there's no supporting reference chain to the owning
object.

For example:

    >>> arr = (ctypes.c_uint * 2**24)()
    >>> arr[-1] = 42
    >>> ref = type(arr).from_address(ctypes.addressof(arr))
    >>> ref[-1]
    42

    >>> ref._b_base_ is None
    True
    >>> ref._objects is None
    True

2**24 bytes is a big allocation that uses mmap (Unix) instead of the
heap. Thus accessing ref[-1] causes a segfault after arr is
deallocated:

    >>> del arr
    >>> ref[-1]
    Segmentation fault (core dumped)



More information about the Python-list mailing list