I've reproduced this behaviour. As you say it's fairly subtle. In fact
I can't tell whether it's a bug at our end or a feature of swig in
general.

It appears that obmol += newmol replaces the underlying OBMol with a
new one. You can see this by printing out the obmol (the address
changes) in a non-segfaulting version:
    mol = pybel.readstring("smi", "C").OBMol
    newmol = pybel.readstring("smi", "C").OBMol
    print mol
    mol += newmol
    print mol
    print pybel.Molecule(mol).write("smi")

<openbabel.OBMol; proxy of <Swig Object of type 'OpenBabel::OBMol *'
at 0x022F5290> >
<openbabel.OBMol; proxy of <Swig Object of type 'OpenBabel::OBMol *'
at 0x028CDF08> >
C.C

If you do the addition in a function, then the mol variable remains
pointing to an OBMol which has been destroyed or something.

If you can find any clues to this in the SWIG docs, I'm happy to try
to fix it but I've just taken a look and don't see anything obvious. I
don't see anything fishy about our C++ code either:
  OBMol &OBMol::operator+=(const OBMol &source)

?

- Noel

On 3 July 2013 11:31, Fred Ludlow <[email protected]> wrote:
> Hi,
>
> I've come across a subtle bug (or misunderstanding on my part..?) when
> merging molecules from python... I've attached a minimal example that
> segfaults (tested on Red Hat Enterprise Linux, python 2.7, openbabel
> 2.3.1). Essentially, it seems that if I do something like
>
> mol1 += mol2
>
> inside a function, mol1 (or more likely the C++ object underneath) is
> no longer valid and doing things like converting it to an output
> string fails with a segfault. I'm guessing swig or python has decided
> there aren't any more references to it and has triggered deletion of
> the C++ object?
> e.g something like:
>
> def addNewFragment(obmol):
>     frag = newFrag() # Create some OBMol instance
>     obmol += frag
>
> mymol = getMol() # Some function to return OBMol instance
> addNewFragment(mymol)
> # At this point the mymol object is broken, and calls to many of its
> methods fail with a segfault
>
>
> Storing another reference to it (e.g. by returning the molecule from
> the function and assigning it to something ) fixes the problem, e.g:
>
> def addNewFragmentAndReturn(obmol):
>    frag = newFrag()
>    obmol += frag
>    return obmol
>
> mymol  =getMol()
> foo = addNewFragmentAndReturn(mymol)
> # mymol is still valid... (creating the "foo" reference seems to have
> kept it alive...)
>
>
> I think this is a bug - Can anyone else reproduce this (demo script
> attached) or is it me not understanding how to use the library :)
>
> Fred
>
> ------------------------------------------------------------------------------
> This SF.net email is sponsored by Windows:
>
> Build for Windows Store.
>
> http://p.sf.net/sfu/windows-dev2dev
> _______________________________________________
> OpenBabel-discuss mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/openbabel-discuss
>

------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
OpenBabel-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openbabel-discuss

Reply via email to