[Python-bugs-list] memory leak in loops (PR#398)

M.-A. Lemburg mal@lemburg.com
Fri, 14 Jul 2000 11:22:51 +0200


ingo.adler@synacon.ch wrote:
> 
> Full_Name: ingo adler
> Version: 1.5.2
> OS: win nt
> Submission from: megazh-d-201.agrinet.ch (212.28.158.201)
> 
> I have a simple loop, which produces memory leaks at every call (36 bytes):
> 
> {
>     Py_SetProgramName("pythontest.exe");
>     Py_Initialize();
> 
>     initxmodulec();
> 
>     PyRun_SimpleString("print \"... Python started ...\"");
> 
>     PyRun_SimpleString("import xmodule");
>     PyRun_SimpleString("from xmodule import *");
> 
> // The Loop
>     PyRun_SimpleString(
>         "y = Y()\n"
>         "for i in range(1000):\n"
>         "\tx = y.getX()\n"
>         "\tx.getNumber()\n"

Could be that SWIG doesn't get a chance to cleanup the shadow
object for x and y. Try adding

del x,y

as final script line.

Note that SWIG uses Python strings to represent pointers in
C++. It uses an internal table to store these.

>     );
> 
>     PyRun_SimpleString("print \"... Python finished ...\"");
>     Py_Finalize();
> }
> 
> X and Y are my classes implemented in C++, connected to Python via Swig Shadow
> Classes:
> 
> class X {
> 
> public:
>     float getNumber()
>     {
>         return 12.2;
>     }
> };
> 
> class Y {
>     X* pX;
> 
> public:
>     Y()
>     {
>         pX = new X;
>     }
> 
>     ~Y()
>     {
>         delete pX;
>     }
> 
>     X* getX()
>     {
>         return pX;
>     }
> };
> 
> The classes and python are compiled statically with CBuilder5.0, Swig1.3a3 (same
> problem with swig1.1).
> 
> I tested the application with "CodeGuard", which shows the memory leaks.
> For every call in the loop there is an entry like this (I translated it to
> English):
> 
> Error. 0x300010 (Thread 0x013B):
> resource leak: memory block (0x15422F0) was never released
> 
> memory leak (0x015422F0) [size: 36 Byte] was assigned with malloc
> call stack:
>    0x0045ED5D(=pythontest.exe:0x01:05DD5D)
> G:\Projects\src\fortuna\Python\Objects\stringobject.c#145
>    0x00401EFD(=pythontest.exe:0x01:000EFD)
> G:\Projects\src\fortuna\test\xmodule_wrap.c#769
>    0x0040255D(=pythontest.exe:0x01:00155D)
> G:\Projects\src\fortuna\test\xmodule_wrap.c#941
>    0x0041BA79(=pythontest.exe:0x01:01AA79)
> G:\Projects\src\fortuna\Python\Python\ceval.c#2359
>    0x0041B912(=pythontest.exe:0x01:01A912)
> G:\Projects\src\fortuna\Python\Python\ceval.c#2324
>    0x0040EE3E(=pythontest.exe:0x01:00DE3E)
> G:\Projects\src\fortuna\Python\Python\bltinmodule.c#12
> 
> The Code for line 941:
> 
> #define Y_getX(_swigobj)  (_swigobj->getX())
> static PyObject *_wrap_Y_getX(PyObject *self, PyObject *args) {
>     Y  *_arg0;
>     PyObject  *_resultobj,*_argo0=0;
>     X  *_result;
>     self = self;
>     if(!PyArg_ParseTuple(args,"O:Y_getX",&_argo0))
>         return NULL;
>     if ((SWIG_ConvertPtr(_argo0,(void **) &_arg0,SWIGTYPE_Y_p,1)) == -1) return
> NULL;
>     _result = (X *)Y_getX(_arg0);
> /*941*/ _resultobj = SWIG_NewPointerObj((void *) _result, SWIGTYPE_X_p);
>     return _resultobj;
> }
> 
> The Code for line 769:
> 
> SWIGSTATICRUNTIME(PyObject *)
> SWIG_NewPointerObj(void *ptr, _swig_type_info *type) {
>   char result[512];
>   PyObject *robj;
>   if (!ptr) {
>     Py_INCREF(Py_None);
>     return Py_None;
>   }
> #ifdef SWIG_COBJECT_TYPES
>   robj = PyCObject_FromVoidPtrAndDesc((void *) ptr, type->name, NULL);
> #else
>   SWIG_MakePtr(result,ptr,type);
> /*769*/  robj = PyString_FromString(result);
> #endif
>   return robj;
> }
> 
> Ingo Adler
> 
> _______________________________________________
> Python-bugs-list maillist  -  Python-bugs-list@python.org
> http://www.python.org/mailman/listinfo/python-bugs-list

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/