[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