summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/arrayobject.c11
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c1
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src16
-rw-r--r--numpy/core/tests/test_scalarmath.py6
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):