Hi Jason. to pinpoint potential memory issues you may run your code through valgrind. For example, it would flag access to previously freed memory in your program:
1 #include <GraphMol/RDKitBase.h> 2 #include <GraphMol/SmilesParse/SmilesParse.h> 3 #include <iostream> 4 5 int main() { 6 auto mol = RDKit::SmilesToMol("CCCC"); 7 auto atom = mol->getAtomWithIdx(0); 8 auto m2 = atom->getOwningMol(); 9 std::cout << "Z=" << atom->getAtomicNum() << std::endl; // prints Z=6 10 delete mol; 11 std::cout << "Z=" << atom->getIdx() << std::endl; // prints Z=0 12 std::cout << "N=" << m2.getNumAtoms() << std::endl;// prints N=4 13 delete atom; // seg fault 14 } $ valgrind ./testmem ==11551== Memcheck, a memory error detector ==11551== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==11551== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==11551== Command: ./testmem ==11551== Z=6 ==11551== Invalid read of size 4 ==11551== at 0x10C924: RDKit::Atom::getIdx() const (Atom.h:133) ==11551== by 0x10B4B6: main (testmem.cpp:11) ==11551== Address 0x5a85a84 is 52 bytes inside a block of size 72 free'd ==11551== at 0x4C2B51D: operator delete(void*) (vg_replace_malloc.c:586) ==11551== by 0x40A5F83: RDKit::ROMol::destroy() (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitGraphMol.so.1.2020.03.5) ==11551== by 0x40AC66E: RDKit::RWMol::~RWMol() (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitGraphMol.so.1.2020.03.5) ==11551== by 0x10B494: main (testmem.cpp:10) ==11551== Block was alloc'd at ==11551== at 0x4C2A593: operator new(unsigned long) (vg_replace_malloc.c:344) ==11551== by 0x4EA4F6B: yysmiles_lex(YYSTYPE*, void*, int&) (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitSmilesParse.so.1.2020.03.5) ==11551== by 0x4E99E8F: yysmiles_parse(char const*, std::vector<RDKit::RWMol*, std::allocator<RDKit::RWMol*> >*, RDKit::Atom*&, RDKit::Bond*&, std::__cxx11::list<unsigned int, std: :allocator<unsigned int> >*, void*, int&) (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitSmilesParse.so.1.2020.03.5) ==11551== by 0x4E5B192: RDKit::(anonymous namespace)::smiles_parse_helper(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<RDKit: :RWMol*, std::allocator<RDKit::RWMol*> >&, RDKit::Atom*&, RDKit::Bond*&, int) (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitSmilesParse.so.1.2020.03.5) ==11551== by 0x4E5B5CA: RDKit::(anonymous namespace)::smiles_parse(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<RDKit::RWMol* , std::allocator<RDKit::RWMol*> >&) (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitSmilesParse.so.1.2020.03.5) ==11551== by 0x4E5CB24: RDKit::toMol(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int (*)(std::__cxx11::basic_string<char, std::char_trai ts<char>, std::allocator<char> > const&, std::vector<RDKit::RWMol*, std::allocator<RDKit::RWMol*> >&), std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/prog/scicomp/pythonds/develop/conda/lib/libRDKitSmilesParse.so.1.2020.03.5) ==11551== by 0x4E63828: RDKit::SmilesToMol(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, RDKit::SmilesParserParams const&) (in /usr/prog/s cicomp/pythonds/develop/conda/lib/libRDKitSmilesParse.so.1.2020.03.5) ==11551== by 0x10D4B8: RDKit::SmilesToMol(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, bool, std::map<std::__cxx11::basic_string<cha r, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::cha r_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<ch ar, std::char_traits<char>, std::allocator<char> > > > >*) (SmilesParse.h:79) ==11551== by 0x10B3DC: main (testmem.cpp:6) ==11551== Cheers, p. On Thu, Aug 27, 2020 at 9:17 PM Jason Biggs <jasondbi...@gmail.com> wrote: > Everything I know about C++ I learned just so that I can write a link > between an interpreted language and the rdkit, so there are definitely some > gaps in my knowledge. > > What I'm trying to understand right now is the expected lifetime of an > Atom pointer returned by a molecule, for instance by the getAtomWithIdx > method. Based on the documentation, since this method doesn't say the user > is responsible for deleting the returned pointer I know I'm not supposed to > delete it. But when exactly does it get deleted? If I dereference it after > deleting the molecule, what is it? > > auto mol = RDKit::SmilesToMol("CCCC"); > auto atom = mol->getAtomWithIdx(0); > auto m2 = atom->getOwningMol(); > std::cout << "Z=" << atom->getAtomicNum() << std::endl; // prints Z=6 > delete mol; > std::cout << "Z=" << atom->getIdx() << std::endl; // prints Z=0 > std::cout << "N=" << m2.getNumAtoms() << std::endl;// prints N=4 > delete atom; // seg fault > > I would have thought the first time dereferencing the atom pointer after > deleting mol would have crashed, but it does not. I would also have > expected bad things when calling the getNumAtoms method on m2 after calling > delete on mol, but this also works just fine. What am I missing? > > Thanks > Jason > _______________________________________________ > Rdkit-discuss mailing list > Rdkit-discuss@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/rdkit-discuss >
_______________________________________________ Rdkit-discuss mailing list Rdkit-discuss@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rdkit-discuss