> I'd like to hear your thoughts about these logs before trying 
> to get into them and understand what's wrong.

The memory losses are sorted by size, so maybe we can try to fix at least the 
biggest memory leaks.

For instance:
==22649== 47,920 bytes in 960 blocks are indirectly lost in loss record 920 of 
921
==22649==    at 0x402471C: operator new(unsigned int) (vg_replace_malloc.c:255)
==22649==    by 0x4E75627: std::basic_string<wchar_t, 
std::char_traits<wchar_t>, std::allocator<wchar_t> >::_Rep::_S_create(unsigned 
int, unsigned int, std::allocator<wchar_t> const&) (in 
/usr/lib/libstdc++.so.6.0.15)
==22649==    by 0x8182DD8: lyx::Paragraph::asString(int, int, int) const 
(basic_string.h:1543)
==22649==    by 0x818C5F7: lyx::Paragraph::collectWords() (Paragraph.cpp:3503)
==22649==    by 0x818C919: lyx::Paragraph::updateWords() (Paragraph.cpp:3531)
...

Refers to:

void Paragraph::collectWords()
{
        // This is the value that needs to be exposed in the preferences
        // to resolve bug #6760.
        static int minlength = 6;
        pos_type n = size();
        for (pos_type pos = 0; pos < n; ++pos) {
                if (isWordSeparator(pos))
                        continue;
                pos_type from = pos;
                locateWord(from, pos, WHOLE_WORD);
                if (pos - from >= minlength) {
                        docstring word = asString(from, pos, AS_STR_NONE);
                        FontList::const_iterator cit = 
d->fontlist_.fontIterator(pos);
                        if (cit == d->fontlist_.end())
                                return;
                        Language const * lang = cit->font().language();
                        d->words_[*lang].insert(word); // HERE HERE HERE HERE 
HERE
                }
        }
}

We call insert on words_[*lang], that is:

class Paragraph::Private {

        [...]

        typedef set<docstring> Words;
        typedef map<Language, Words> LangWordsMap;
        ///
        LangWordsMap words_;

        [...]

};

In the destructor:

Paragraph::~Paragraph()
{
        deregisterWords();
        delete d;
}

void Paragraph::deregisterWords()
{
        Private::LangWordsMap::const_iterator itl = d->words_.begin();
        Private::LangWordsMap::const_iterator ite = d->words_.end();
        for (; itl != ite; ++itl) {
                WordList * wl = theWordList(itl->first);
                Private::Words::const_iterator it = (itl->second).begin();
                Private::Words::const_iterator et = (itl->second).end();
                for (; it != et; ++it)
                        wl->remove(*it);
        }
        d->words_.clear();
}

But in wl->remove...

void WordList::remove(docstring const & w)
{
        Impl::Words::iterator it = d->words_.find(w);
        if (it != d->words_.end()) {
                it.data()--;
                d->words_.change_weight(it, 0);
                // We will not erase here, but instead we just leave it
                // in the btree with weight 0. This avoid too much
                // reorganisation of the tree all the time.
                //if (it.data() == 0)
                //      d->words_.erase(w);
        }
}

If I'm correct we're not removing the words to avoid tree reorganization, but 
when we call delete d; in the destructor all the data remains orphan: 47,920 
bytes are indirectly lost.

This is a serious memory leak IMHO, as paragraph are created and destroyed 
quite frequently.

venom00

Reply via email to