How to identify memory leaks in extensions?
Travis Oliphant
olipt at mayo.edu
Fri May 12 02:27:17 EDT 2000
> > The short answer is, everything must be DECREF'd.
>
> okay. i am confused now. even if one is __returning__ the array?
>
I'm sorry for the confusion. Of course you should NOT DECREF arrays you
are going to return (unless you INCREF'd them for some reason in your
code), or your process will lose the memory previously allocated for them.
***
*** I meant you should DECREF everything you don't want to have a
*** increased reference for when your done with the subroutine.
***
> ==============================
> ...
> indep = (PyArrayObject *) PyArray_FromDims( IND_DIM, &dims[1], PyArray_DOUBLE);
> dep = (PyArrayObject *) PyArray_FromDims( DEP_DIM, dims, PyArray_DOUBLE);
>
> indepPtr = (double *)indep->data;
>
> /* now let PyArray_As2D re-arrange, if necessary (?), */
> /* our array and set the pointers to the rows of array */
> PyArray_As2D( (PyObject**)&dep, (char ***) &numarr,
> &dims[0], &dims[1], PyArray_DOUBLE );
>
>
> /* do stuff */
>
> return Py_BuildValue("(OO)", indep, dep);
> ==============================
>
> okay, from your post those 'OO' should be 'NN'. but even then ...
>
Yes, no need to DECREF if you use "(NN)" (since you do want these
variables to stay around after you leave this subroutine).
> > Whenever you use a PyArray_XXXXXXX construct that gives you back a
> > PyArrayObject, you own a reference. You must DECREF before leaving
> > the subroutine or you have a memory leak.
Change this to. You must DECREF before leaving the subroutine if you
did not intend to have an increased reference count.
>
> you're saying i have to DECREF indep and dep before i return????? its
> confusing. i allocate arrays with PyArrayXXX to do stuff with and
> return them, in my python code i set references to them. somehow the
> 'setting reference in the python code' is an INCREF over and above the
> PyArrayXXX?
No I don't think so. I didn't mean to imply that. If you want to return
the array don't DECREF it (unless you use "O" in Py_BuildValue).
>
> so, lets see. every PyArray does one INCREF. every Py_BuildValue does
> another one if you use the 'O', and when you set a refernece equal to
> it in a return value, thats yet another?????? or maybe i am confusing
> the last INCREF with the first one.
I don't think the last INCREF happens, so don't let my quick explanation
confuse you.
>
> but if i go
>
> x = 3
> y = x
>
> that y = adds a reference to the 3 object.
>
> thanks
This is my understanding of this sequence:
x=3:
"3" is evaluated (because "3" is an integer between -1 and 100, the
the reference count to the integer 3 is incremented and a
pointer to the object is returned). So the evaluation does the
INCREF.
Since x is a name it binds this name to the returned object (no further
reference count increase).
y = x
The reference count of x is incremented during evaluation of x and
a reference is returned. This reference is bound to y. Again, the
INCREF happens at evaluation.
x = 4
"4" is evaluated as before, INCREF'ing the reference count. Now since
x is already bound, the object x references ("3") is DECREF'd. Then,
the new object (with it's already increased reference count) is bound
to the name ("x").
The language reference leads me to believe that this is sort of how it
works. I have not carefully looked through this part of the Python source
code, however. This model lets me write code that does not have memory
problems, however.
Good luck,
Travis
More information about the Python-list
mailing list