[docs] [issue15821] PyMemoryView_FromBuffer() behavior change (possible regression)

Stefan Krah report at bugs.python.org
Sat Sep 1 09:33:42 CEST 2012


Stefan Krah added the comment:

In general, the number of calls to PyObject_GetBuffer() must be equal to
the number of calls to PyBuffer_Release(), otherwise bad things will happen
in the same way as with malloc()/free().


Now, in my test case I omitted the call to PyObject_GetBuffer() *with*
the internal knowledge that in the case of the bytes object it does
not matter: The releasebufferproc is NULL, so PyBuffer_Release()
is just a way of decrementing the reference count of the bytes object.


No matter how you turn it, if info.obj != NULL you need some internal
knowledge what the obj's releasebufferproc will do. For example, I
suspect that many existing releasebufferprocs do not account for
the fact that a consumer may change shape, strides and suboffsets.

So you need to know the exporter really well.


My strategy here is this: I want to keep backwards compatibility
for PyMemoryView_FromBuffer(), which I think should be deprecated
at some point.


A proper function that returns a memoryview with automatic cleanup
would not involve getbuffer/releasebuffer at all and could look like
this:

Flags:
------
    PyManagedBuffer_FreeBuf
    PyManagedBuffer_FreeFormat
    PyManagedBuffer_FreeArrays  // shape, strides, suboffsets

PyMemoryView_FromBufferWithCleanup(info, flags)
{
    /* info should never have been obtained by a call to PyObject_GetBuffer().
       Hence it should never be released. */
    assert(info.obj == NULL);

    /* buf, format, shape, strides and suboffsets MUST stay valid
       for the lifetime of the returned memoryview. Usually they
       will be dynamically allocated using PyMem_Malloc(). This is
       no problem, since there is automatic cleanup in mbuf_dealloc(). */

    mbuf = mbuf_alloc();
    mbuf->master = *info;
    mbuf->flags |= flags;

    ...

    return new memoryview
}

mbuf_dealloc(self)
{
    if (self->flags&PyManagedBuffer_FreeBuf)
        PyMem_Free(self->master.buf);
    ...
}

This is much more flexible than the existing function and does not suffer
from any abuse of getbuffer/releasebuffer.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue15821>
_______________________________________


More information about the docs mailing list