[Pyrex] Re: Memory leak when returning inside a for loop

j.kartnaller j.kartnaller at robotech.at
Mon Oct 17 17:01:18 CEST 2005


Here is a test case to reproduce the memory leak :

The pyrex code :

------------------------------------------------------------------
def noMemoryLeak():
     for i in range(10):
         break

def memoryLeak():
     for i in range(10):
         return
------------------------------------------------------------------

The problem in the C-Code for the memoryLeak function :

------------------------------------------------------------------
static PyObject *__pyx_f_4leak_memoryLeak(PyObject *__pyx_self, PyObject 
*__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_i;
   PyObject *__pyx_r;
   PyObject *__pyx_1 = 0;
   PyObject *__pyx_2 = 0;
   PyObject *__pyx_3 = 0;
   static char *__pyx_argnames[] = {0};
   if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "", __pyx_argnames)) 
return 0;
   __pyx_v_i = Py_None; Py_INCREF(__pyx_v_i);

   /* "C:\pj\pyrex\memleak\leak.pyx":6 */
   __pyx_1 = __Pyx_GetName(__pyx_b, __pyx_n_range); if (!__pyx_1) 
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; goto __pyx_L1;}
   __pyx_2 = PyInt_FromLong(10); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; 
__pyx_lineno = 6; goto __pyx_L1;}
   __pyx_3 = PyTuple_New(1); if (!__pyx_3) {__pyx_filename = __pyx_f[0]; 
__pyx_lineno = 6; goto __pyx_L1;}
   PyTuple_SET_ITEM(__pyx_3, 0, __pyx_2);
   __pyx_2 = 0;
   __pyx_2 = PyObject_CallObject(__pyx_1, __pyx_3); if (!__pyx_2) 
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; goto __pyx_L1;}
   Py_DECREF(__pyx_1); __pyx_1 = 0;
   Py_DECREF(__pyx_3); __pyx_3 = 0;
   __pyx_1 = PyObject_GetIter(__pyx_2); if (!__pyx_1) {__pyx_filename = 
__pyx_f[0]; __pyx_lineno = 6; goto __pyx_L1;}
   Py_DECREF(__pyx_2); __pyx_2 = 0;
   for (;;) {
     __pyx_L2:;
     __pyx_3 = PyIter_Next(__pyx_1);
     if (!__pyx_3) {
       if (PyErr_Occurred()) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; 
goto __pyx_L1;}
       break;
     }
     Py_DECREF(__pyx_v_i);
     __pyx_v_i = __pyx_3;
     __pyx_3 = 0;

     /* "C:\pj\pyrex\memleak\leak.pyx":7 */
     __pyx_r = Py_None; Py_INCREF(__pyx_r);
     goto __pyx_L0;
   }
   __pyx_L3:;
   Py_DECREF(__pyx_1); __pyx_1 = 0;

   __pyx_r = Py_None; Py_INCREF(__pyx_r);
   goto __pyx_L0;
   __pyx_L1:;

Here the ref count for the range is decremented :

   Py_XDECREF(__pyx_1);
   Py_XDECREF(__pyx_2);
   Py_XDECREF(__pyx_3);
   __Pyx_AddTraceback("leak.memoryLeak");
   __pyx_r = 0;

But the return statement jumps here and never decrements the ref count for the 
range :

   __pyx_L0:;
   Py_DECREF(__pyx_v_i);
   return __pyx_r;
}
------------------------------------------------------------------


Hope this helps.

Jürgen


Greg Ewing wrote:
> j.kartnaller wrote:
> 
>> If a method is doing a "return" from inside a for loop I get a memory 
>> leak.
>> It was reproducable in all my methods which are doing this.
>>
>> Is this a known problem ?
>> If not I will try to build a test case for this.
> 
> 
> I don't think I've heard of this before. A test case
> would be useful, thanks.
> 




More information about the Pyrex mailing list