8000 ENH: fix and test for blindly taking ownership of data · numpy/numpy@e81eff4 · GitHub
[go: up one dir, main page]

Skip to content

Commit e81eff4

Browse files
committed
ENH: fix and test for blindly taking ownership of data
1 parent 522c368 commit e81eff4

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

numpy/core/src/multiarray/arrayobject.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,17 @@ array_dealloc(PyArrayObject *self)
501501
if (nbytes == 0) {
502502
nbytes = fa->descr->elsize ? fa->descr->elsize : 1;
503503
}
504-
PyDataMem_UserFREE(fa->data, nbytes, fa->mem_handler);
505-
Py_DECREF(fa->mem_handler);
504+
if (fa->mem_handler == NULL) {
505+
char const * msg = "Trying to dealloc data, but a memory policy "
506+
"is not set. If you take ownership of the data, you must "
507+
"also set a memory policy.";
508+
WARN_IN_DEALLOC(PyExc_RuntimeWarning, msg);
509+
// Guess at malloc/free ???
510+
free(fa->data);
511+
} else {
512+
PyDataMem_UserFREE(fa->data, nbytes, fa->mem_handler);
513+
Py_DECREF(fa->mem_handler);
514+
}
506515
}
507516

508517
/* must match allocation in PyArray_NewFromDescr */

numpy/core/tests/test_mem_policy.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import pytest
33
import numpy as np
44
import threading
5-
from numpy.testing import extbuild
5+
import warnings
6+
from numpy.testing import extbuild, assert_warns
67
import sys
78

89

@@ -40,6 +41,25 @@ def get_module(tmp_path):
4041
Py_DECREF(old);
4142
Py_RETURN_NONE;
4243
"""),
44+
("get_array", "METH_NOARGS", """
45+
char *buf = (char *)malloc(20);
46+
npy_intp dims[1];
47+
dims[0] = 20;
48+
PyArray_Descr *descr = PyArray_DescrNewFromType(NPY_UINT8);
49+
return PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, NULL,
50+
buf, NPY_ARRAY_WRITEABLE, NULL);
51+
"""),
52+
("set_own", "METH_O", """
53+
if (!PyArray_Check(args)) {
54+
PyErr_SetString(PyExc_ValueError,
55+
"need an ndarray");
56+
return NULL;
57+
}
58+
PyArray_ENABLEFLAGS((PyArrayObject*)args, NPY_ARRAY_OWNDATA);
59+
// Maybe try this too?
60+
// PyArray_BASE(PyArrayObject *)args) = NULL;
61+
Py_RETURN_NONE;
62+
"""),
4363
]
4464
prologue = '''
4565
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
@@ -305,3 +325,14 @@ 94C0 def test_new_policy(get_module):
305325

306326
c = np.arange(10)
307327
assert np.core.multiarray.get_handler_name(c) == orig_policy_name
328+
329+
def test_switch_owner(get_module):
330+
a = get_module.get_array()
331+
assert np.core.multiarray.get_handler_name(a) is None
332+
get_module.set_own(a)
333+
with warnings.catch_warnings():
334+
warnings.filterwarnings('always')
335+
# The policy should be NULL, so we have to assume we can call "free"
336+
with assert_warns(RuntimeWarning) as w:
337+
del a
338+
print(w)

0 commit comments

Comments
 (0)
0