Issue 33267: ctypes array types create reference cycles (original) (raw)

Discovered in https://github.com/numpy/numpy/pull/10882/files#r180813166

A reproduction:

In [1]: import ctypes

In [2]: def make_array_ctype(shape):
   ...:     import ctypes
   ...:     ct = ctypes.c_uint8
   ...:     for i in shape:
   ...:         ct = i * ct
   ...:     return ct
   ...:

# all on one line to keep ipython out of this
In [3]: gc.collect(); x = make_array_ctype((1,)); del x; gc.collect()

Using the proposed function in https://github.com/numpy/numpy/pull/10891, we get a few more details:

In [4]: from numpy.testing import assert_no_gc_cycles

In [5]: assert_no_gc_cycles(make_array_ctype, (1,))
AssertionError: Reference cycles were found when calling make_array_ctype: 7 objects were collected, of which 6 are shown below:
  tuple object with id=2822255556536:
    (<class '_ctypes.Array'>,)
  PyCArrayType object with id=2822226500408:
    <class '__main__.c_ubyte_Array_1'>
  getset_descriptor object with id=2822252062256:
    <attribute '__dict__' of 'c_ubyte_Array_1' objects>
  getset_descriptor object with id=2822252062184:
    <attribute '__weakref__' of 'c_ubyte_Array_1' objects>
  tuple object with id=2822243712440:
    (<class '__main__.c_ubyte_Array_1'>,
     <class '_ctypes.Array'>,
     <class '_ctypes._CData'>,
     <class 'object'>)
  StgDict object with id=2822226211928:
    {'__dict__': <attribute '__dict__' of 'c_ubyte_Array_1' objects>,
     '__doc__': None,
     '__module__': '__main__',
     '__weakref__': <attribute '__weakref__' of 'c_ubyte_Array_1' objects>,
     '_length_': 1,
     '_type_': <class 'ctypes.c_ubyte'>}

I suppose this isn't really a bug, but it's not clear to me why a cycle needs to be created here.