← Back to team overview

dolfin team mailing list archive

Re: [PyCC-dev] Segmentation fault

 

On Thu, Nov 01, 2007 at 09:57:59AM +0100, Martin Sandve Alnæs wrote:
> 2007/11/1, Anders Logg <logg@xxxxxxxxx>:
> > On Thu, Nov 01, 2007 at 07:50:15AM +0100, Martin Sandve Alnæs wrote:
> > > 2007/11/1, Anders Logg <logg@xxxxxxxxx>:
> > > > On Wed, Oct 31, 2007 at 10:10:42AM +0100, Martin Sandve Alnæs wrote:
> > > > > 2007/10/31, Martin Sandve Alnæs <martinal@xxxxxxxxx>:
> > > > > > 2007/10/30, Ola Skavhaug <skavhaug@xxxxxxxxx>:
> > > > > > > Anders Logg skrev den 30/10-2007 følgende:
> > > > > > > > The following code gives me a segmentation fault:
> > > > > > > >
> > > > > > > >   from dolfin import *
> > > > > > > >
> > > > > > > >   def foo():
> > > > > > > >       element = FiniteElement("Lagrange", "triangle", 1)
> > > > > > > >       mesh = UnitSquare(2, 2)
> > > > > > > >       return Function(element, mesh, 1.0)
> > > > > > > >
> > > > > > > >   print foo().mesh().numVertices()
> > > > > > > >
> > > > > > > > If the mesh is declared outside foo() it works fine.
> > > > > > > >
> > > > > > > > It seems that Python is calling the Mesh destructor when foo()
> > > > > > > > returns. It shouldn't since the Function created in foo() keeps a
> > > > > > > > reference to the mesh.
> > > > > > > >
> > > > > > > > Does anyone know how to fix this? Is it possible to tell Python that
> > > > > > > > the mesh is referenced by the function?
> > > > > > >
> > > > > > > Take a look at the swig documentation. It might be possible to add some
> > > > > > > directives for this, but it is a major problem. Even the Python bindings for
> > > > > > > vtk have this flaw.
> > > > > >
> > > > > > This is also the same as the memory handling issues we haven't given
> > > > > > any serious thought in the GenericTensor hierarchy: A = Matrix();
> > > > > > assemble(A); A = A.mat(); who owns the underlying PetSCMatrix or
> > > > > > EpetraMatrix now?
> > > > > >
> > > > > > If you can accept a common base class with a reference count for all
> > > > > > dolfin classes, and using str::tr1::shared_ptr in the C++ code, it can
> > > > > > be solved (at least for most use cases).
> > > > >
> > > > > Sorry, that won't work for the linear algebra classes, because it
> > > > > would require a reference count located in the Mat object (with
> > > > > PetSC).
> > > >
> > > > The PETSc Mat pointer is created in the constructor of
> > > > dolfin::PETScMatrix and destroyed in the destructor so we have full
> > > > control over it.
> > >
> > > I think that's the best solution, since it's easy to understand, but
> > > it doesn't solve the problem. Let me just explain what the problem is:
> > >
> > > # If the user does
> > > def foo(...):
> > >     A = PETScMatrix()
> > >     assemble(A, ...)
> > >     return A.mat()
> > >
> > > A = foo(...)
> > > # ... do PETSc stuff only
> > >
> > > At this point the PETScMatrix is deleted, deleting the Mat, and A is
> > > invalid. The solution is for the user to store the PETScMatrix
> > > reference somewhere, but that kind of destroys the convenience of
> > > reference counting in the first place... This is the same pattern as
> > > your mesh example.
> >
> > This is not a big problem right now since no one (?) is using PETSc
> > calls from Python.
> >
> > > > What is str::tr1::shared_ptr???
> > > >
> > > > /Anders
> > >
> > > I meant std, std::tr1::shared_ptr
> > >
> > > It's a reference counted smart pointer, from the boost project but now
> > > part of the C++ standard called Technical Report 1, which will be
> > > merged into the C++ standard library at some point. Should be
> > > supported by most modern compilers now.
> > >
> > >
> > > #include <tr1/memory>
> > > ...
> > > {
> > >   std::tr1::shared_ptr<Foo> mypointer2;
> > >   {
> > >     std::tr1::shared_ptr<Foo> mypointer = new Foo();
> > >     mypointer2 = mypointer;
> > >   }
> > > } // Foo object is deleted here
> >
> > ok, perhaps this could be worked into the class dolfin::Variable that
> > many of the classes in DOLFIN inherit from?
> >
> > /Anders
> 
> You don't need to do anything to your own classes to use shared_ptr in
> C++. But using shared_ptr in Python isn't feasible, so in that case
> the reference count must be located in the object itself. Thus a
> reference count could be included in dolfin::Variable. Then you can
> let swig know about your incref/decref functions in Variable, and it
> will use that instead of deleting the object from the Python side. But
> you should use shared_ptr<Foo> instead of Foo* in your C++ code as
> well, and pass a custom deleter object to the shared_ptr constructor
> to make it use the reference count in Variable.

ok, let's talk about it in detail when I return.

/Anders


References