Commit 68f92630 authored by Stefan Behnel's avatar Stefan Behnel

fix memory leak for memory views in extension subtypes

parent 58c7a899
......@@ -15,6 +15,10 @@ Features added
Bugs fixed
----------
* Memory leak when extension subtypes add a memory view as attribute
to those of the parent type without having Python object attributes
or a user provided dealloc method.
* Compiler crash on readonly properties in "binding" mode.
* Auto-encoding with ``c_string_encoding=ascii`` failed in Py3.3.
......
......@@ -1768,6 +1768,7 @@ class CClassScope(ClassScope):
# method_table_cname string
# getset_table_cname string
# has_pyobject_attrs boolean Any PyObject attributes?
# has_memoryview_attrs boolean Any memory view attributes?
# has_cyclic_pyobject_attrs boolean Any PyObject attributes that may need GC?
# property_entries [Entry]
# defined boolean Defined in .pxd file
......@@ -1777,6 +1778,7 @@ class CClassScope(ClassScope):
is_c_class_scope = 1
has_pyobject_attrs = False
has_memoryview_attrs = False
has_cyclic_pyobject_attrs = False
defined = False
implemented = False
......@@ -1850,7 +1852,9 @@ class CClassScope(ClassScope):
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
self.var_entries.append(entry)
if type.is_pyobject and name != '__weakref__':
if type.is_memoryviewslice:
self.has_memoryview_attrs = True
elif type.is_pyobject and name != '__weakref__':
self.has_pyobject_attrs = True
if (not type.is_builtin_type
or not type.scope or type.scope.needs_gc()):
......
......@@ -353,6 +353,7 @@ class ConstructorSlot(InternalMethodSlot):
if (self.slot_name != 'tp_new'
and scope.parent_type.base_type
and not scope.has_pyobject_attrs
and not scope.has_memoryview_attrs
and not scope.lookup_here(self.method)):
# if the type does not have object attributes, it can
# delegate GC methods to its parent - iff the parent
......
"""
Test for memory leaks when adding more memory view attributes in subtypes.
"""
import gc
from cython.view cimport array
def count_memoryviews():
gc.collect()
return sum([1 if 'memoryview' in str(type(o)) else 0
for o in gc.get_objects()])
def run_test(cls, num_iters):
orig_count = count_memoryviews()
def f():
x = cls(1024)
for i in range(num_iters):
f()
return count_memoryviews() - orig_count
cdef class BaseType:
"""
>>> run_test(BaseType, 10)
0
"""
cdef double[:] buffer
def __cinit__(self, n):
self.buffer = array((n,), sizeof(double), 'd')
cdef class Subtype(BaseType):
"""
>>> run_test(Subtype, 10)
0
"""
cdef double[:] buffer2
def __cinit__(self, n):
self.buffer2 = array((n,), sizeof(double), 'd')
cdef class SubtypeWithUserDealloc(BaseType):
"""
>>> run_test(SubtypeWithUserDealloc, 10)
0
"""
cdef double[:] buffer2
def __cinit__(self, n):
self.buffer2 = array((n,), sizeof(double), 'd')
def __dealloc__(self):
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment