Hello. We have Client/server socket application (multiple clients and servers). Servers are multiplatform can be compiled for Windows (MSVC) and for Linux (GCC). Recently we detected memory leak in one of kinde of our servers. At the start it uses only 15m (that is normally). Then it slowly grows up to 2000m within 2 weeks. Only Linux+GCC version was affected by this problem. We have checked our server by valgrind. It detected leak. The leak is possible in std::vectot<int>::reserve()or in std::vectot<int>::clear() I use GCC 3.4.5 builded and installed on Fedora Core 2 REproduceable: Always. The code producing leak: ... typedef int card_type; typedef int Funds; …. const size_t MAX_CARDS_ON_HAND = 7; typedef std::vector<card_type> CardsSet; ... //---------------------------------------------------------------------------- class CBaseSeat : public ISerializable { public: CBaseSeat(); void standUpSeat(); ... protected: unsigned m_flags; Funds m_cash; Funds m_bet; CardsSet m_cardsSet; }; //---------------------------------------------------------------------------- CBaseSeat::CBaseSeat() : m_flags(0), m_cash(0), m_bet(0), m_cardsSet() { m_cardsSet.reserve( MAX_CARDS_ON_HAND ); standUpSeat(); } //---------------------------------------------------------------------------- void CBaseSeat::standUpSeat() { m_flags = 0; m_cash = 0; m_bet = 0; m_cardsSet.clear(); } When we comment this line // m_cardsSet.reserve( MAX_CARDS_ON_HAND ); The leak is Gone. I just can suppose that the problem in reserve() or in clear() method whick called imediately after reserve(); Please see Valgrind report: (after several minutes of work) ==22501== 124,376 bytes in 4,442 blocks are definitely lost in loss record 6 of 6 ==22501== at 0x43B8B10: operator new(unsigned) (vg_replace_malloc.c:164) ==22501== by 0x806B2F9: __gnu_cxx::new_allocator<int>::allocate(unsigned, void const*) (new_allocator.h:81) ==22501== by 0x806B191: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned) (stl_vector.h:113) ==22501== by 0x807DD9C: int* std::vector<int, std::allocator<int> >::_M_allocate_and_copy<int*>(unsigned, int*, int*) (stl_vector.h:715) ==22501== by 0x807DC96: std::vector<int, std::allocator<int> >::reserve(unsigned) (vector.tcc:78) ==22501== by 0x80842E7: Poker::CBaseSeat::CBaseSeat() (seat.cpp:20) ==22501== by 0x807123D: Poker::CClientSeat::CClientSeat(Poker::CClientSeat const&) (seat.h:134) ==22501== by 0x80711FC: void std::_Construct<Poker::CClientSeat, Poker::CClientSeat>(Poker::CClientSeat*, Poker::CClientSeat const&) (stl_construct.h:81) ==22501== by 0x8072FB8: __gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > > std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > >, unsigned, Poker::CClientSeat>(__gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > >, unsigned, Poker::CClientSeat const&, __false_type) (stl_uninitialized.h:194) ==22501== by 0x8072C5B: __gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > > std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > >, unsigned, Poker::CClientSeat>(__gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > >, unsigned, Poker::CClientSeat const&) (stl_uninitialized.h:219) ==22501== by 0x8072682: std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> >::_M_fill_insert(__gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > >, unsigned, Poker::CClientSeat const&) (vector.tcc:314) ==22501== by 0x8071CF3: std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> >::insert(__gnu_cxx::__normal_iterator<Poker::CClientSeat*, std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> > >, unsigned, Poker::CClientSeat const&) (stl_vector.h:612) ==22501== by 0x8070CAC: std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> >::resize(unsigned, Poker::CClientSeat const&) (stl_vector.h:398) ==22501== by 0x806FE22: std::vector<Poker::CClientSeat, std::allocator<Poker::CClientSeat> >::resize(unsigned) (stl_vector.h:412) ==22501== by 0x806C0AB: Poker::CClientGameState::read(std::istream&) (clientgamestate.cpp:144) ==22501== by 0x80B4430: Poker::CSelfHolder<Poker::CClientGameState>::read(std::istream&) (holder.h:147) ==22501== by 0x808BE86: Poker::CMessage::read(std::istream&) (message.cpp:71) ==22501== by 0x80A8D54: Poker::CMessageFactory::createFromStream(Poker::CSession*, std::istream&) (messagesfactory.cpp:1206) ==22501== by 0x80E49F1: Poker::CRawDistiler::read(Poker::ISocket*, Poker::CServerSession*) (distiler.cpp:180) ==22501== by 0x80E29E5: Poker::CConnection::recieveMessages() (connection.cpp:94) ==22501== by 0x80E29A3: Poker::CConnection::doWork() (connection.cpp:81) ==22501== by 0x80E6E49: Poker::CLobbyClient::doWork() (lobbyclient.cpp:123) ==22501== by 0x80F827D: Poker::CBot::doWork() (bot.cpp:174) ==22501== by 0x80FE742: Poker::CBotServer::doWork() (botserver.cpp:32) ==22501== by 0x81028DB: main (main.cpp:35) Hope my information will be usefull
Can you provide a complete program which demonstrates this link? I've tried looking at the code in question myself, and cannot observe a memory leak myself.
Chris is right. Certainly we are not aware of any problem in that code, in particular the 3.4.5 version, very close to the original HP/SGI code and very well tested from that point of view (at least). Please provide a self-contained testcase (as small as possible, of course), otherwise the PR, not really useful, likely will be soon closed, sorry.
Ok, i will try to create a short program
I have tried to create simple test case (about 200 rows) where I tried to reproduce key code fragments. In simple test case leak not reproduced. But I have easy reproduced it with very small application based on main project code. Code like CMessage* m1 = theMessageFactory.createInstance( …) CMessage* m2 = m1->clone(); delete m2; delete m1; I am staring think that problem in templates instantiation. Also I already had problem with proper template instantiation in my Project. For some copy operations with vector of objects, vptr were set to 0 (caused SEG FAULT). I have not reported on It. I have resolved it by equal code but without copy operation. (2 weeks spent to detect cause, I though I am was wrong somewhere  ) I have a test executable with full debug info (27M) (necessary libs statically linked) Depends only ldd ./leaktest linux-gate.so.1 => (0x00f56000) libstdc++.so.6 => /usr/local/lib/libstdc++.so.6 (0x00111000) libm.so.6 => /lib/tls/libm.so.6 (0x0045c000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x005a5000) libc.so.6 => /lib/tls/libc.so.6 (0x00339000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00320000) Will it be usefull for you? To analyze generated code.
(In reply to comment #4) > I have tried to create simple test case (about 200 rows) where I tried to > reproduce key code fragments. In simple test case leak not reproduced. But I > have easy reproduced it with very small application based on main project code. Please try harder to produce a self-contained, small, testcase. Otherwise, we cannot debug the issue. Thanks.
My natural suspision would be that your clone() function is incorrectly implemented. Can you show us the source to the CMessage object, and theMessageFactory.createInstance( …)?
Hello. Now I can say more about this problem. before code listing I am sure that problem in template instantiation. code if CBaseSeat::CBaseSeat() id used deeply in templates holder<T1> contains T1 which contains of vector<Derived from BaseSeat> which contains vector<int> there are facts: 1) The leak was gone just i removed line m_cardsSet.reserve( MAX_CARDS_ON_HAND ); it was need only for allocatio optimize 2) Windows version of this code not affected by this problem In any case i will try to create self contained test code when i will have a day for it. But it will be rather big i think. There is the code: //---------------------------------------------------------------------------------------- CMessage* CMessage::clone() const { CMessage* result = new CMessage( m_descriptor, m_session, m_id ); std::stringstream buffer; this->write( buffer ); // read unnecessary type short type; shortSerializer.read( buffer, type ); result->read( buffer ); return result; } //---------------------------------------------------------------------------------------- CMessage* CMessageFactory::createInstance( CSession* sess, MessageType type ) { Descriptors::iterator pos = m_descriptors.find( type ); if( pos==m_descriptors.end() ) { throw std::logic_error("ERROR: Trying create message of unknown type" ); } CMessage* result = new CMessage( pos->second, sess, nextMessageId() ); return result; }
One quick piece of advice. Have you tried compiling your entire application against the libstdc++ debug mode? It might help narrow down where the problem is.
Feedback not forthcoming.