From: SourceForge.net <no...@so...> - 2007-11-14 21:10:40
|
Bugs item #1832054, was opened at 2007-11-14 16:10 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101645&aid=1832054&group_id=1645 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: python Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Robert Lupton the Good (rhl-astro) Assigned to: Marcelo Matus (marcelomatus) Summary: %implicitconv can lead to a double free Initial Comment: (Previously posted to swig-users) I have a couple of problems with swig (1.3.31 or svn) related to smart pointers; both lead to a double free. This is C++/python. I've appended a complete test case, but the basics are: A simple C++ class Image defined in Image.h a .i file saying: %module badfree ... %include "Image.h" %template(ImagePtrT) boost::shared_ptr<Image >; (The .i file needs its own version of boost::shared_ptr as swig can't handle %include <boost::shared_ptr.hpp>, a problem I've reported before but never resolved). With this, the statements import badfree im = badfree.Image(10, 20) iptr = badfree.ImagePtrT(im) del im del iptr free the Image twice, as the ImagePtrT constructor doesn't realise that python thinks that im still owns the object. I'm not exactly sure that this is a bug, but it is a problem. It's one that I can workaround by defining a macro that defines ImagePtrT() to disown im (see appended .i file; one can also change the boost::smart_ptr definition in the .i file), but I think that this should be a swig macro not mine. With this disown in place, the above code works just fine. But if I add %implicitconv boost::shared_ptr<Image>; (directly or via %extend_smart_pointer) I get a double free again. I don't know how to work around this one -- help! R ------------------------------------------------------------------------ ----------------badfree.i: // -*- c++ -*- %module badfree %{ #include <boost/shared_ptr.hpp> #include "Image.h" %} /* * Don't expose the entire boost::shared_ptr to swig; it is complicated... */ namespace boost { template<class T> class shared_ptr { public: // Copy constructor *must* come before the bare pointer constructor. This is because a // shared_ptr<T> * is convertible to a T * via SWIG_ConvertPtr, so if the SWIG generated constructor // argument dispatching function doesn't first test to see if an incoming argument is a shared_ptr<T> *, // double deletes will occur shared_ptr(shared_ptr<T> const &); shared_ptr(T *); ~shared_ptr(); T *operator->() const; int use_count() const; T *get() const; }; } %include "Image.h" / ************************************************************************ ******/ // // Work around a swig 1.33.1 bug wherein swig doesn't realise that python still // owns the pointer that's now wrapped in a shared_ptr // %define smart_pointer(NAME, TYPE, PTR_TYPE) // The next three lines are equivalent to %extend_smart_pointer (PTR_TYPE<TYPE >); %implicitconv PTR_TYPE<TYPE >; %apply const SWIGTYPE& SMARTPOINTER { const PTR_TYPE<TYPE >& }; %apply SWIGTYPE SMARTPOINTER { PTR_TYPE<TYPE > }; %template(NAME) PTR_TYPE<TYPE >; #if 1 %extend PTR_TYPE<TYPE > { %pythoncode %{ __oldInit__ = __init__ def __init__(self, *args): args[0].this.disown() self.__oldInit__(args[0]) %} }; #endif %enddef %define boost_shared_ptr(NAME, TYPE) smart_pointer(NAME, TYPE, boost::shared_ptr) %enddef / ************************************************************************ ******/ boost_shared_ptr(ImagePtrT, Image); %{ int Image::_gid = 0; Image::Image(int nrow, int ncol) : _nrow(nrow), _ncol(ncol) { _id = _gid++; printf("In Image(): %d\n", _id); } Image::~Image() { printf("In ~Image(): %d\n", _id); } %} ------------------------------------------------------------------------ ----------------Image.h: #include <boost/shared_ptr.hpp> class Image { public: Image(int nrow, int ncol); ~Image(); int rows() const { return _nrow; } int cols() const { return _ncol; } int id() const { return _id; } private: int _nrow, _ncol; int _id; static int _gid; }; ------------------------------------------------------------------------ ----------------Makefile (os/x): #BOOST_DIR = /foo/bar/boost COMMONFLAGS = -I$(BOOST_DIR)/include CXXFLAGS = $(COMMONFLAGS) -fPIC -I. -I$(PYTHON_DIR)/include/python2.5 SWIGFLAGS = $(COMMONFLAGS) -c++ -python SOFLAGS = -bundle -flat_namespace _badfree.so : badfree_wrap.o $(CC) -o _badfree.so $(SOFLAGS) badfree_wrap.o \ -L$(PYTHON_DIR)/lib/python2.5/site-packages -lpython badfree_wrap.cc : badfree.i swig $(SWIGFLAGS) -o badfree_wrap.cc badfree.i clean : $(RM) badfree.py *_wrap.* *.pyc *~ core.* *.o *.so ------------------------------------------------------------------------ ---------------- demo.py: #BOOST_DIR = /foo/bar/boost COMMONFLAGS = -I$(BOOST_DIR)/include CXXFLAGS = $(COMMONFLAGS) -fPIC -I. -I$(PYTHON_DIR)/include/python2.5 SWIGFLAGS = $(COMMONFLAGS) -c++ -python SOFLAGS = -bundle -flat_namespace _badfree.so : badfree_wrap.o $(CC) -o _badfree.so $(SOFLAGS) badfree_wrap.o \ -L$(PYTHON_DIR)/lib/python2.5/site-packages -lpython badfree_wrap.cc : badfree.i swig $(SWIGFLAGS) -o badfree_wrap.cc badfree.i clean : $(RM) badfree.py *_wrap.* *.pyc *~ core.* *.o *.so ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101645&aid=1832054&group_id=1645 |