Opened 13 years ago

Closed 8 years ago

#4089 closed Bugs (invalid)

Memory leak in Boost.Signals2 when the signal is not invoked

Reported by: dan.berindei@… Owned by: Frank Mori Hess
Milestone: To Be Determined Component: signals2
Version: Boost 1.55.0 Severity: Problem
Keywords: Cc:

Description

The attached program leaks memory by attaching and detaching slots from a signal in a loop:

boost::signals2::signal<void(void)> sig;
boost::signals2::connection conn1, conn2, conn3, conn4;

while (true) {
    conn1.disconnect();
    conn2.disconnect();

    conn1 = sig.connect(slot);
    conn2 = sig.connect(slot);

    conn3.disconnect();
    conn4.disconnect();

    conn3 = sig.connect(slot);
    conn4 = sig.connect(slot);

    //sig();
}

Invoking the signal (i.e. uncommenting the 'sig()' line) plugs the memory leak, however in my original setting it entails lots of unnecessary work so it's not a very good solution.

My guess is that _garbage_collector_it is set to _shared_state->connection_bodies().end() on invocation, but not on a new connection, so it never goes back to the beginning of the list.

Attachments (1)

aaa.cpp (599 bytes ) - added by dan.berindei@… 13 years ago.
Leak Test

Download all attachments as: .zip

Change History (7)

by dan.berindei@…, 13 years ago

Attachment: aaa.cpp added

Leak Test

comment:1 by Frank Mori Hess, 13 years ago

(In [61243]) Fix for uncontrolled growth of slot list under certain patterns of connection/disconnection without invocation. Refs #4089.

comment:2 by Frank Mori Hess, 13 years ago

Resolution: fixed
Status: newclosed

(In [61278]) Merged from trunk to release. Fixes #4089.

comment:3 by julien.puydt@…, 8 years ago

Milestone: Boost 1.43.0To Be Determined
Resolution: fixed
Status: closedreopened
Version: Boost 1.42.0Boost 1.55.0

The following code gives wrong results with 1.55.0 ; it shows kept references trough a disconnection, which get released only if the signal is triggered :

#include <boost/smart_ptr.hpp>
#include <boost/signals2.hpp>
#include <iostream>

void
print (boost::shared_ptr<int> & ptr)
{
  std::cout << "Pointer has use count: " << ptr.use_count () << std::endl;
}

int
main (int argc,
      char* argv[])
{
  boost::signals2::signal<void(void)> sig;
  boost::shared_ptr<int> ptr(new int);

  // one ref here: should be 1
  print (ptr);

  boost::signals2::connection conn = sig.connect (boost::bind (&print, ptr));

  // one ref here, one in the bind: should be 2
  print (ptr);

  // is supposed to release the bind reference
  conn.disconnect ();

  // one ref here: should be 1
  print (ptr);

  // this isn't supposed to release a reference!
  sig ();

  // one ref here: should be 1
  print (ptr);

  return 0;
}

comment:4 by Frank Mori Hess, 8 years ago

The behavior described by the most recent comment is by design and not a memory leak. There is already a ticket (#8533) to change the designed behavior to what you were expecting.

comment:5 by julien.puydt@…, 8 years ago

It's what I was expecting because that's what I used to have. Though I can't tell if it was with signals v1 or v2...

comment:6 by Frank Mori Hess, 8 years ago

Resolution: invalid
Status: reopenedclosed
Note: See TracTickets for help on using tickets.