[issue41883] ctypes pointee goes out of scope, then pointer in struct dangles and crashes
Eryk Sun
report at bugs.python.org
Tue Sep 29 01:46:01 EDT 2020
Eryk Sun <eryksun at gmail.com> added the comment:
I think this is a numpy issue. Its data_as() method doesn't support the ctypes _objects protocol to keep the numpy array referenced by subsequently created ctypes objects. For example:
import ctypes
import numpy as np
dtype = ctypes.c_double
ptype = ctypes.POINTER(dtype)
class array_struct(ctypes.Structure):
_fields_ = (('dim1', ctypes.c_int),
('dim2', ctypes.c_int),
('ptr', ptype))
n = 12
m = 50
a = np.ones((n, m), dtype=dtype)
p = a.ctypes.data_as(ptype)
data_as() is implemented as a cast() of the ctypes._data pointer. This is a c_void_p instance for the base address of the numpy array, but it doesn't reference the numpy array object itself. The pointer returned by cast() references this _data pointer in its _objects:
>>> p._objects
{139993690976448: c_void_p(42270224)}
data_as() also sets a reference to the numpy array object as a non-ctypes _arr attribute:
>>> p._arr is a
True
This _arr attribute keeps the array referenced for the particular instance, but ctypes isn't aware of it. When the object returned by data_as() is set in a struct, ctypes only carries forward the c_void_p reference from _objects that it's aware of:
>>> a_wrap1 = array_struct(n, m, p)
>>> a_wrap1._objects
{'2': {139993690976448: c_void_p(42270224)}}
It would be sufficient to keep the numpy array alive if this c_void_p instance referenced the array, but it doesn't. Alternatively, data_as() could update the _objects dict to reference the array. For example:
>>> p._objects['1'] = a
>>> a_wrap2 = array_struct(n, m, p)
>>> a_wrap2._objects['2']['1'] is a
True
----------
nosy: +eryksun
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue41883>
_______________________________________
More information about the Python-bugs-list
mailing list