[C++-sig] memory leaks using the "manage_new_object"return policy...
Kevin Jones
investtcartier at yahoo.com
Wed Sep 20 18:22:49 CEST 2006
Roman Yakovenko <roman.yakovenko <at> gmail.com> writes:
>
> On 9/14/06, Kevin Jones <investtcartier <at> yahoo.com> wrote:
> > Hi,
> >
> > I am using the manage_new_object return policy to wrap
> > "newed" C++ object in an effort to conserve memory.
> >
> > Even though I am deleting the returned object in
> > Python and invoking the Python garbage collector I
> > still have a leak. This is a long-running systems
> > adminstration app the read the contents of a very
> > large database.
> >
> > Any suggestions on how to make manage_new_object
> > behave correctly?
>
> May be I can help. I am just going through "same" process. It is up to
> you to prove
> that boost.python does not free the memory. So if you create small test case
> ( one cpp, one Python script, Jamfile ) that reproduce the error, I
> think you will get the answer\solution to your problem pretty quick.
>
Roman,
It turns out that the leak is in the return_by_value policy and *not* the
manage_new_object policy.
I am converting a "newed" C++ instance to a Python object and the C++ instance
gets dropped on the floor (I.e. - not "deleted").
The sample source code is as follows in boosttest.py and BoostTest.cpp:
Note: The name of the generated DLL is _boosttest.dll in my example.
Kevin
boosttest.py:
-------------
import _boosttest
import os, sys, gc, random
import msvcrt
for i in range(100000):
x = _boosttest.make(random.randint(1,1000))
val = x[0]
del x
del val
gc.collect()
BoostTest.cpp:
#include <vector>
#include "boostpython.h"
class BoostTest
{
public:
int getSize(){return v.size();}
void append(int x){v.push_back(x);}
int getItem(int i){return v[i];}
private:
std::vector<int> v;
};
// Factory function for free store instances of BoostTest
BoostTest* make(int n)
{
BoostTest* b = new BoostTest();
for(int i=0;i<n;i++)
{
b->append(i);
}
return b;
}
struct BoostTest_to_p
{
static PyObject* convert(BoostTest* x);
};
PyObject* BoostTest_to_p::convert(BoostTest* x)
{
PyObject* list = PyList_New(0);
if(list == NULL) return Py_None;
const int n = x->getSize();
for(int i=0;i<n;i++)
{
PyObject* item = PyInt_FromLong(x->getItem(i));
if( item == NULL || item == Py_None )
{
Py_DECREF(list);
list = Py_None;
break;
}
PyList_Append(list,item);
}
return list;
}
BOOST_PYTHON_MODULE(_boosttest)
{
to_python_converter<BoostTest*, BoostTest_to_p>();
def("make", make, return_value_policy<return_by_value>());
class_<BoostTest>("BoostTest",no_init)
.def("getSize", &BoostTest::getSize)
.def("append", &BoostTest::append)
.def("__getitem__",&BoostTest::getItem);
}
More information about the Cplusplus-sig
mailing list