Re: [Boost-bugs] [Boost C++ Libraries] #738: Memory leaks with signal::connect?

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #738: Memory leaks with signal::connect?
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2008-04-29 18:29:14


#738: Memory leaks with signal::connect?
----------------------+-----------------------------------------------------
  Reporter: dgregor | Owner: dgregor
      Type: Bugs | Status: new
 Milestone: | Component: signals
   Version: None | Severity: Showstopper
Resolution: None | Keywords:
----------------------+-----------------------------------------------------
Changes (by dgregor):

  * owner: doug_gregor => dgregor

Old description:

> {{{
>
> Hello,
>
> I'm sending this message a second time (I didn't receive any response
> and still
> have this problem)
>
> I'm using boost::bind and boost::signal with VC6. VC6 is detecting
> some memory
> leak for a certain type of signal.connect(). I've done a little test
> program
> to
> check if the problem was due to some bug or special configuration in
> my main
> program, but the memory leaks are still detected in the test situation.
>
> Let me explain the structure of my test program. I have a main, and in
> the main,
> an object CCloneAppRecipe named clone. The class CCloneAppRecipe
> contains a
> member m_PtrTestMem (a shared pointer, but a raw point or an object
> does the
> same thing) of the class CTestMem. CTestMem contains 3 instances of
> the class
> CTestTab, and the class CTestTab contains a boost signal
>
> typedef boost::signal0<void> TypeSignalTest;
> TypeSignalTest m_SignalTest;
>
> In my main, I invoke clone.connectPtrTestMem().
> clone.connectPtrTestMem() then invokes
> CTestMem::ConnectSignalTriplePtrTab(boost::bind
> (&CloneAppRecipe::test, this));
> ConnectSignalTriplePtrTab() then invokes ConnectSignal
> (TypeSignalTest::slot_type
> slot) for each of the 3 instances of the class it contains.
> ConnectSignal then calls m_SignalTest.connect(slot).
>
> And I have a memory leak: 2 blocks of 16 bytes. If I connect only one
> instance
> of CTestTab, no leak. Two instances, one leak of 16 bytes. Three, two
> leaks of
> 16 bytes, and so on.
>
> I connect the m_SignalTest with a CCloneAppRecipe's slot. If I connect
> it to a
> CTestMem slot, I have no leak. Or if I place 3 instances of CTestTab
> directly
> in the CCloneAppRecipe class (so I don't use CTestMem anymore), I
> have no leak.
> But that's not what I need to do. I've tested plenty of variations
> (shared_pointer or object, etc.) Does anybody have a clue.
>
> Thanks
>

> #include "stdafx.h"
> #include "CloneAppRecipe.h"
>
> #ifdef _DEBUG
> #define new DEBUG_NEW
> #undef THIS_FILE
> static char THIS_FILE[] = __FILE__;
> #endif
>

>
> int main()
> {
> CloneAppRecipe t;
> // cree un leak
> t.connectPtrTestMem();
> getchar();
> return 0;
> }
>

> void CloneAppRecipe::connectPtrTestMem()
> {
> //m_ptrTestMem is a boost::shared_ptr
> m_ptrTestMem->ConnectSignalTriplePtrTab(boost::bind
> (&CloneAppRecipe::test,
> this));
>
> }
>
> void CloneAppRecipe::test() const
> {
> }
>
> void CTestMem::ConnectSignalTriplePtrTab(const
> TypeSignaTest::slot_type& slot)
> {
> //m_ptrTestTab are boost::shared_ptr
> m_ptrTestTab1->ConnectSignal(slot);
> m_ptrTestTab2->ConnectSignal(slot);
> m_ptrTestTab3->ConnectSignal(slot);
> }
>
> void CTestTab::ConnectSignal(const TypeSignalTest::slot_type& slot)
> {
> m_SignalTest->connect(slot);
> }
>
> CTestTab::~CTestTab()
> {
> m_SignalTest->disconnect_all_slots();
> }
>

>
> here is my complete test program.
>
> // TestMemBis.cpp : Defines the entry point for the console
> application.
> //
>
> #include "stdafx.h"
> #include "CloneAppRecipe.h"
>
> #ifdef _DEBUG
> #define new DEBUG_NEW
> #undef THIS_FILE
> static char THIS_FILE[] = __FILE__;
> #endif
>

>
> int main()
> {
> CloneAppRecipe t;
> // cree un leak
> t.connectPtrTestMem();
>
> getchar();
> return 0;
> }
>
> // CloneAppRecipe.h: interface for the CloneAppRecipe class.
> //
> //////////////////////////////////////////////////////////////////
> ////
>
> #if !defined(AFX_CLONEAPPREC__INCLUDED_)
> #define AFX_CLONEAPPREC__INCLUDED_
>
> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000
>
> #include "TestMem.h"
>
> class CloneAppRecipe
> {
> public:
>
> CloneAppRecipe();
> ~CloneAppRecipe();
>

> private:
> // desactive constructeur copie et operateur=
> CloneAppRecipe( const CloneAppRecipe& rhs );
> CloneAppRecipe& operator=( const CloneAppRecipe& rhs );
>
> // slot pour connecter
> void test() const;
> public:
> void connectPtrTestMem();
>
> boost::shared_ptr<TestMem> m_ptrTestMem;
>
> };
>
> #endif
>
> // CloneAppRecipe.cpp: implementation of the CloneAppRecipe class.
> //
> //////////////////////////////////////////////////////////////////
> ////
>

> #include "stdafx.h"
> #include "CloneAppRecipe.h"
> #include "TestTab.h"
>

> #ifdef _DEBUG
> #define new DEBUG_NEW
> #undef THIS_FILE
> static char THIS_FILE[] = __FILE__;
> #endif
>
> CloneAppRecipe::CloneAppRecipe() : m_ptrTestMem( new TestMem() )
> {
> }
>
> CloneAppRecipe::~CloneAppRecipe()
> {
> }
>
> void CloneAppRecipe::test() const
> {
> }
>
> void CloneAppRecipe::connectPtrTestMem()
> {
> m_ptrTestMem->ConnectSignal(boost::bind
> (&CloneAppRecipe::test, this));
>
> }
>

>
> // TestMem.h: interface for the TestMem class.
> //
> //////////////////////////////////////////////////////////////////
> ////
>
> #if !defined(AFX_TESTMEM__INCLUDED_)
> #define AFX_TESTMEM__INCLUDED_
>
> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000
>
> class TestTab;
>
> class TestMem
> {
> public:
> typedef boost::signal0<void> TypeSignalTest;
>
> TestMem();
> ~TestMem();
>
> void ConnectSignal(const TypeSignalTest::slot_type& slot) const;
>

> private:
> // desactive constructeur copie et operateur=
> TestMem( const TestMem& rhs );
> TestMem& operator=( const TestMem& rhs );
>

> boost::shared_ptr<TestTab> m_ptrTestTab1;
> boost::shared_ptr<TestTab> m_ptrTestTab2;
> boost::shared_ptr<TestTab> m_ptrTestTab3;
>
> };
>
> #endif //
> !defined
> (AFX_VISIONPARAMTABMANAGER_H__F0F26B98_D7D0_489E_AD5F_0D
> DEBF9A2D4F__INCLUDED_)
>
> // TestMem.cpp: implementation of the TestMem class.
> //
> //////////////////////////////////////////////////////////////////
> ////
>

> #include "stdafx.h"
> #include "TestMem.h"
> #include "TestTab.h"
>

> #ifdef _DEBUG
> #define new DEBUG_NEW
> #undef THIS_FILE
> static char THIS_FILE[] = __FILE__;
> #endif
>
> TestMem::TestMem()
> : m_ptrTestTab1( new TestTab() ),
> m_ptrTestTab2( new TestTab() ),
> m_ptrTestTab3( new TestTab() )
> {
> }
>
> TestMem::~TestMem()
> {
>
> }
>

> void TestMem::ConnectSignal(const TypeSignalTest::slot_type& slot)
> const
> {
> m_ptrTestTab1->ConnectSignal(slot);
> m_ptrTestTab2->ConnectSignal(slot);
> m_ptrTestTab3->ConnectSignal(slot);
> }
>
> // VisionParamGenericTab.h: interface for the CVisionParamGenericTab
> class.
> //
> //////////////////////////////////////////////////////////////////
> ////
>
> #if !defined(AFX_TEST_TAB)
> #define AFX_TEST_TAB
>
> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000
>

> typedef boost::signal0<void> TypeSignalTest;
>

> class TestTab
> {
> public:
>
> TestTab();
> ~TestTab();
>
> void ConnectSignal(const TypeSignalTest::slot_type& slot);
>
> private:
> // desactive constructeur copie
> TestTab( const TestTab& rhs );
> TestTab& operator=( const TestTab& rhs );
>
> TypeSignalTest m_SignalTest;
>
> };
>
> #endif
>
> // TestTab.cpp: implementation of the TestTab class.
> //
> //////////////////////////////////////////////////////////////////
> ////
>
> #include "stdafx.h"
> #include "TestTab.h"
>
> #ifdef _DEBUG
> #define new DEBUG_NEW
> #undef THIS_FILE
> static char THIS_FILE[] = __FILE__;
> #endif
>

> TestTab::TestTab()
> {
>
> }
>
> TestTab::~TestTab()
> {
> m_SignalTest.disconnect_all_slots();
> }
>
> void TestTab::ConnectSignal(const TypeSignalTest::slot_type& slot)
> {
> m_SignalTest.connect(slot);
> }
>

>
> // stdafx.h : include file for standard system include files,
> // or project specific include files that are used frequently, but
> // are changed infrequently
> //
>
> #if !defined
> (AFX_STDAFX_H__4BC26E01_A411_43B7_9129_B453770CBE84__INCLU
> DED_)
> #define
> AFX_STDAFX_H__4BC26E01_A411_43B7_9129_B453770CBE84__INCLU
> DED_
>
> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000
>
> #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff
> from Windows headers
>
> #include <stdio.h>
> #include <afx.h>
> #include "CloneGeneral.h"
> #include "BoostIInclude.h"
>

> #endif //
> !defined
> (AFX_STDAFX_H__4BC26E01_A411_43B7_9129_B453770CBE84__INCLU
> DED_)
>

> CloneGeneral.h
> #define
> AFX_GENERAL_H__F3520E35_333F_11D5_A855_000103C25D02__INCL
> UDED_
>
> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000
>
> //#define for if (1) for // TODO_PASSAGE_6.0_8.0
>

> #define BOOST_NO_INTRINSIC_WCHAR_T // requis parce que
> BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_integral,wchar_t,true)
> // est
> défini 2 fois sinon et
> ca ne compile pas.
>
> // disable auto-linking for Boost
> #define BOOST_ALL_NO_LIB
>
> #endif //
> !defined
> (AFX_GENERAL_H__F3520E35_333F_11D5_A855_000103C25D02__INC
> LUDED_)
>

>
> BoostIInclude.h
> #if !defined
> (AFX_SVBOOSTBIND_H__F3520E35_333F_11D5_A855_000103C25D02_
> _INCLUDED_)
> #define
> AFX_SVBOOSTBIND_H__F3520E35_333F_11D5_A855_000103C25D02__
> INCLUDED_
>
> #pragma warning(push,1)
> #include "boost/bind.hpp"
> #include "boost/signal.hpp"
> #include "boost/shared_ptr.hpp"
> #pragma warning(pop)
>
> #ifdef _DEBUG
> #pragma comment(lib, "libboost_signals-vc6-mt-gd.lib")
> #else
> #pragma comment(lib, "libboost_signals-vc6-mt.lib")
> #endif
>
> #endif //
> !defined
> (AFX_SVBOOSTBIND_H__F3520E35_333F_11D5_A855_000103C25D02_
> _INCLUDED_)
>

> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
> }}}

New description:

 {{{

 Hello,

 I'm sending this message a second time (I didn't receive any response
 and still
 have this problem)

 I'm using boost::bind and boost::signal with VC6. VC6 is detecting
 some memory
 leak for a certain type of signal.connect(). I've done a little test
 program
 to
 check if the problem was due to some bug or special configuration in
 my main
 program, but the memory leaks are still detected in the test situation.

 Let me explain the structure of my test program. I have a main, and in
 the main,
 an object CCloneAppRecipe named clone. The class CCloneAppRecipe
 contains a
 member m_PtrTestMem (a shared pointer, but a raw point or an object
 does the
 same thing) of the class CTestMem. CTestMem contains 3 instances of
 the class
 CTestTab, and the class CTestTab contains a boost signal

 typedef boost::signal0<void> TypeSignalTest;
 TypeSignalTest m_SignalTest;

 In my main, I invoke clone.connectPtrTestMem().
 clone.connectPtrTestMem() then invokes
 CTestMem::ConnectSignalTriplePtrTab(boost::bind
 (&CloneAppRecipe::test, this));
 ConnectSignalTriplePtrTab() then invokes ConnectSignal
 (TypeSignalTest::slot_type
 slot) for each of the 3 instances of the class it contains.
 ConnectSignal then calls m_SignalTest.connect(slot).

 And I have a memory leak: 2 blocks of 16 bytes. If I connect only one
 instance
 of CTestTab, no leak. Two instances, one leak of 16 bytes. Three, two
 leaks of
 16 bytes, and so on.

 I connect the m_SignalTest with a CCloneAppRecipe's slot. If I connect
 it to a
 CTestMem slot, I have no leak. Or if I place 3 instances of CTestTab
 directly
 in the CCloneAppRecipe class (so I don't use CTestMem anymore), I
 have no leak.
 But that's not what I need to do. I've tested plenty of variations
 (shared_pointer or object, etc.) Does anybody have a clue.

 Thanks


 #include "stdafx.h"
 #include "CloneAppRecipe.h"

 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif



 int main()
 {
         CloneAppRecipe t;
         // cree un leak
         t.connectPtrTestMem();
         getchar();
         return 0;
 }


 void CloneAppRecipe::connectPtrTestMem()
 {
         //m_ptrTestMem is a boost::shared_ptr
         m_ptrTestMem->ConnectSignalTriplePtrTab(boost::bind
 (&CloneAppRecipe::test,
 this));

 }

 void CloneAppRecipe::test() const
 {
 }

 void CTestMem::ConnectSignalTriplePtrTab(const
 TypeSignaTest::slot_type& slot)
 {
         //m_ptrTestTab are boost::shared_ptr
         m_ptrTestTab1->ConnectSignal(slot);
         m_ptrTestTab2->ConnectSignal(slot);
         m_ptrTestTab3->ConnectSignal(slot);
 }

 void CTestTab::ConnectSignal(const TypeSignalTest::slot_type& slot)
 {
         m_SignalTest->connect(slot);
 }

 CTestTab::~CTestTab()
 {
         m_SignalTest->disconnect_all_slots();
 }



 here is my complete test program.

 // TestMemBis.cpp : Defines the entry point for the console
 application.
 //

 #include "stdafx.h"
 #include "CloneAppRecipe.h"

 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif



 int main()
 {
         CloneAppRecipe t;
         // cree un leak
         t.connectPtrTestMem();

         getchar();
         return 0;
 }

 // CloneAppRecipe.h: interface for the CloneAppRecipe class.
 //
 //////////////////////////////////////////////////////////////////
 ////

 #if !defined(AFX_CLONEAPPREC__INCLUDED_)
 #define AFX_CLONEAPPREC__INCLUDED_

 #if _MSC_VER > 1000
 #pragma once
 #endif // _MSC_VER > 1000

 #include "TestMem.h"

 class CloneAppRecipe
 {
 public:

         CloneAppRecipe();
         ~CloneAppRecipe();


 private:
         // desactive constructeur copie et operateur=
         CloneAppRecipe( const CloneAppRecipe& rhs );
         CloneAppRecipe& operator=( const CloneAppRecipe& rhs );

         // slot pour connecter
         void test() const;
 public:
         void connectPtrTestMem();

         boost::shared_ptr<TestMem> m_ptrTestMem;

 };

 #endif

 // CloneAppRecipe.cpp: implementation of the CloneAppRecipe class.
 //
 //////////////////////////////////////////////////////////////////
 ////


 #include "stdafx.h"
 #include "CloneAppRecipe.h"
 #include "TestTab.h"


 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif

 CloneAppRecipe::CloneAppRecipe() : m_ptrTestMem( new TestMem() )
 {
 }

 CloneAppRecipe::~CloneAppRecipe()
 {
 }

 void CloneAppRecipe::test() const
 {
 }

 void CloneAppRecipe::connectPtrTestMem()
 {
         m_ptrTestMem->ConnectSignal(boost::bind
 (&CloneAppRecipe::test, this));

 }



 // TestMem.h: interface for the TestMem class.
 //
 //////////////////////////////////////////////////////////////////
 ////

 #if !defined(AFX_TESTMEM__INCLUDED_)
 #define AFX_TESTMEM__INCLUDED_

 #if _MSC_VER > 1000
 #pragma once
 #endif // _MSC_VER > 1000

 class TestTab;

 class TestMem
 {
 public:
         typedef boost::signal0<void> TypeSignalTest;

         TestMem();
         ~TestMem();

         void ConnectSignal(const TypeSignalTest::slot_type& slot) const;


 private:
         // desactive constructeur copie et operateur=
         TestMem( const TestMem& rhs );
         TestMem& operator=( const TestMem& rhs );


         boost::shared_ptr<TestTab> m_ptrTestTab1;
         boost::shared_ptr<TestTab> m_ptrTestTab2;
         boost::shared_ptr<TestTab> m_ptrTestTab3;

 };

 #endif //
 !defined
 (AFX_VISIONPARAMTABMANAGER_H__F0F26B98_D7D0_489E_AD5F_0D
 DEBF9A2D4F__INCLUDED_)

 // TestMem.cpp: implementation of the TestMem class.
 //
 //////////////////////////////////////////////////////////////////
 ////


 #include "stdafx.h"
 #include "TestMem.h"
 #include "TestTab.h"


 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif

 TestMem::TestMem()
 : m_ptrTestTab1( new TestTab() ),
         m_ptrTestTab2( new TestTab() ),
         m_ptrTestTab3( new TestTab() )
 {
 }

 TestMem::~TestMem()
 {

 }


 void TestMem::ConnectSignal(const TypeSignalTest::slot_type& slot)
 const
 {
         m_ptrTestTab1->ConnectSignal(slot);
         m_ptrTestTab2->ConnectSignal(slot);
         m_ptrTestTab3->ConnectSignal(slot);
 }

 // VisionParamGenericTab.h: interface for the CVisionParamGenericTab
 class.
 //
 //////////////////////////////////////////////////////////////////
 ////

 #if !defined(AFX_TEST_TAB)
 #define AFX_TEST_TAB

 #if _MSC_VER > 1000
 #pragma once
 #endif // _MSC_VER > 1000


 typedef boost::signal0<void> TypeSignalTest;


 class TestTab
 {
 public:

         TestTab();
         ~TestTab();

         void ConnectSignal(const TypeSignalTest::slot_type& slot);

 private:
     // desactive constructeur copie
         TestTab( const TestTab& rhs );
         TestTab& operator=( const TestTab& rhs );

         TypeSignalTest m_SignalTest;

 };

 #endif

 // TestTab.cpp: implementation of the TestTab class.
 //
 //////////////////////////////////////////////////////////////////
 ////

 #include "stdafx.h"
 #include "TestTab.h"

 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif


 TestTab::TestTab()
 {

 }

 TestTab::~TestTab()
 {
         m_SignalTest.disconnect_all_slots();
 }

 void TestTab::ConnectSignal(const TypeSignalTest::slot_type& slot)
 {
         m_SignalTest.connect(slot);
 }



 // stdafx.h : include file for standard system include files,
 // or project specific include files that are used frequently, but
 // are changed infrequently
 //

 #if !defined
 (AFX_STDAFX_H__4BC26E01_A411_43B7_9129_B453770CBE84__INCLU
 DED_)
 #define
 AFX_STDAFX_H__4BC26E01_A411_43B7_9129_B453770CBE84__INCLU
 DED_

 #if _MSC_VER > 1000
 #pragma once
 #endif // _MSC_VER > 1000

 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff
 from Windows headers

 #include <stdio.h>
 #include <afx.h>
 #include "CloneGeneral.h"
 #include "BoostIInclude.h"


 #endif //
 !defined
 (AFX_STDAFX_H__4BC26E01_A411_43B7_9129_B453770CBE84__INCLU
 DED_)


 CloneGeneral.h
 #define
 AFX_GENERAL_H__F3520E35_333F_11D5_A855_000103C25D02__INCL
 UDED_

 #if _MSC_VER > 1000
 #pragma once
 #endif // _MSC_VER > 1000

 //#define for if (1) for // TODO_PASSAGE_6.0_8.0


 #define BOOST_NO_INTRINSIC_WCHAR_T // requis parce que
 BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_integral,wchar_t,true)
                                                                    // est
 défini 2 fois sinon et
 ca ne compile pas.

 // disable auto-linking for Boost
 #define BOOST_ALL_NO_LIB

 #endif //
 !defined
 (AFX_GENERAL_H__F3520E35_333F_11D5_A855_000103C25D02__INC
 LUDED_)



 BoostIInclude.h
 #if !defined
 (AFX_SVBOOSTBIND_H__F3520E35_333F_11D5_A855_000103C25D02_
 _INCLUDED_)
 #define
 AFX_SVBOOSTBIND_H__F3520E35_333F_11D5_A855_000103C25D02__
 INCLUDED_

 #pragma warning(push,1)
 #include "boost/bind.hpp"
 #include "boost/signal.hpp"
 #include "boost/shared_ptr.hpp"
 #pragma warning(pop)

 #ifdef _DEBUG
     #pragma comment(lib, "libboost_signals-vc6-mt-gd.lib")
 #else
     #pragma comment(lib, "libboost_signals-vc6-mt.lib")
 #endif

 #endif //
 !defined
 (AFX_SVBOOSTBIND_H__F3520E35_333F_11D5_A855_000103C25D02_
 _INCLUDED_)


 Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼Ã¯Â¿Â¼_______________________________________________
 Boost-users mailing list
 Boost-users_at_[hidden]
 http://lists.boost.org/mailman/listinfo.cgi/boost-users

 }}}

--
Ticket URL: <http://svn.boost.org/trac/boost/ticket/738#comment:2>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.


This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:57 UTC