diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/arrayobject.c | 11 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 1 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalartypes.c.src | 16 | ||||
-rw-r--r-- | numpy/core/tests/test_scalarmath.py | 6 |
4 files changed, 29 insertions, 5 deletions
diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c index 1d4cebd8f..bf843f7f8 100644 --- a/numpy/core/src/multiarray/arrayobject.c +++ b/numpy/core/src/multiarray/arrayobject.c @@ -1684,6 +1684,13 @@ array_alloc(PyTypeObject *type, Py_ssize_t NPY_UNUSED(nitems)) return obj; } +static PyObject * +array_free(PyObject * v) +{ + /* avoid same deallocator as PyBaseObject, see gentype_free */ + PyObject_Free(v); +} + NPY_NO_EXPORT PyTypeObject PyArray_Type = { #if defined(NPY_PY3K) @@ -1738,9 +1745,9 @@ NPY_NO_EXPORT PyTypeObject PyArray_Type = { 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)0, /* tp_init */ - array_alloc, /* tp_alloc */ + (allocfunc)array_alloc, /* tp_alloc */ (newfunc)array_new, /* tp_new */ - 0, /* tp_free */ + (freefunc)array_free, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 008fdb68c..9b584dcf9 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -4153,7 +4153,6 @@ PyMODINIT_FUNC initmultiarray(void) { if (!d) { goto err; } - PyArray_Type.tp_free = PyObject_Free; if (PyType_Ready(&PyArray_Type) < 0) { return RETVAL; } diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 8b7269676..9c081f150 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -128,6 +128,18 @@ gentype_dealloc(PyObject *v) Py_TYPE(v)->tp_free(v); } +static void +gentype_free(PyObject *v) +{ + /* + * have an explicit tp_free to enforce inheritance from it. + * PyObject_Free is also the tp_free of PyBaseObject so python does not + * COPYSLOT it, instead it takes the next parent PyInt which has a + * different allocator + */ + PyObject_Free(v); +} + static PyObject * gentype_power(PyObject *m1, PyObject *m2, PyObject *NPY_UNUSED(m3)) @@ -3985,7 +3997,7 @@ initialize_numeric_types(void) PyGenericArrType_Type.tp_getset = gentype_getsets; PyGenericArrType_Type.tp_new = NULL; PyGenericArrType_Type.tp_alloc = gentype_alloc; - PyGenericArrType_Type.tp_free = PyObject_Free; + PyGenericArrType_Type.tp_free = gentype_free; PyGenericArrType_Type.tp_repr = gentype_repr; PyGenericArrType_Type.tp_str = gentype_str; PyGenericArrType_Type.tp_richcompare = gentype_richcompare; @@ -4009,7 +4021,7 @@ initialize_numeric_types(void) PyBoolArrType_Type.tp_as_number->nb_index = (unaryfunc)bool_index; PyStringArrType_Type.tp_alloc = NULL; - PyStringArrType_Type.tp_free = PyObject_Free; + PyStringArrType_Type.tp_free = NULL; PyStringArrType_Type.tp_repr = stringtype_repr; PyStringArrType_Type.tp_str = stringtype_str; diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index 7bbb62be2..c6919d43e 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -45,6 +45,12 @@ class TestTypes(TestCase): b = atype([1, 2, 3]) assert_equal(a, b) + def test_leak(self): + # test leak of scalar objects + # a leak would show up in valgrind as still-reachable of ~2.6MB + for i in range(200000): + np.add(1, 1) + class TestBaseMath(TestCase): def test_blocked(self): |