在单个 slot_type 上使用多个 boost::connect 导致内存泄漏
当我尝试将多个信号连接到单个 slot_type
时,我正在使用 boost::signals
并泄漏内存。我在各个论坛上看到过同样的泄漏报告,但找不到任何提到执行此操作的正确方法或任何解决方法的内容。
我想做的事情:
我试图将 boost::bind() 的结果传递到函数中。在此函数中,我想将多个信号连接到该结果。第一个连接工作正常,但第一个连接之后的每个连接都会泄漏句柄。
以下是一些示例代码:
typedef boost::signal0<void> LeakSignalType;
class CalledClass
{
/* ... */
void connectToSlots(LeakSignalType::slot_type &aSlot)
{
LeakSignalType *sig;
std::list<LeakSignalType*> sigList;
std::list<LeakSignalType*>::iterator sigIter;
for(int i = 0; i < 50; i++)
{
/*Connect signals to the passed slot */
sig = new LeakSignalType;
sig->connect(aSlot);
sigList.push_back(sig);
}
for(sigIter = sigList.begin(); sigIter != sigList.end(); sigIter++)
{
/* Undo everything we just did */
delete *sigIter;
}
sigList.clear();
/*Everything should be cleaned up now */
}
/* ... */
}
class CallingClass : public boost::signals::trackable
{
CalledClass calledInstance;
/* ... */
void boundFunction(int i)
{
/*Do Something*/
}
void connectSignals()
{
calledInstance.connectToSlots(boost::bind( &CallingClass::boundFunction, this, 1));
}
/* ... */
};
现在调用 CallingClass::connectSignals()
。
我预计对 connectToSlots
的调用会将 50 个信号连接到单个插槽,然后断开连接并清理所有这些信号。实际发生的情况是,1 个信号完全清理,然后其余 49 个信号部分清理,但泄漏了一些内存。
将插槽传递到函数中以供多次使用的正确方法是什么?任何帮助将不胜感激。
谢谢, 克里斯
I'm using boost::signals
and leaking memory when I try to connect multiple signals to a single slot_type
. I've seen this same leak reported on various forums, but can't find any that mention the correct way to do this, or any workaround.
What I am trying to do:
I am trying to pass the result of boost::bind()
into a function. In this function, I want to connect multiple signals to that result. The first connect works fine, but every connect after the first will leak a handle.
Here is some sample code:
typedef boost::signal0<void> LeakSignalType;
class CalledClass
{
/* ... */
void connectToSlots(LeakSignalType::slot_type &aSlot)
{
LeakSignalType *sig;
std::list<LeakSignalType*> sigList;
std::list<LeakSignalType*>::iterator sigIter;
for(int i = 0; i < 50; i++)
{
/*Connect signals to the passed slot */
sig = new LeakSignalType;
sig->connect(aSlot);
sigList.push_back(sig);
}
for(sigIter = sigList.begin(); sigIter != sigList.end(); sigIter++)
{
/* Undo everything we just did */
delete *sigIter;
}
sigList.clear();
/*Everything should be cleaned up now */
}
/* ... */
}
class CallingClass : public boost::signals::trackable
{
CalledClass calledInstance;
/* ... */
void boundFunction(int i)
{
/*Do Something*/
}
void connectSignals()
{
calledInstance.connectToSlots(boost::bind( &CallingClass::boundFunction, this, 1));
}
/* ... */
};
Now call CallingClass::connectSignals()
.
I expect that the call to connectToSlots
will connect 50 signals to a single slot, then disconnect and clean up all of those signals. What actually happens is that 1 signal completely cleans up, then the remaining 49 partially clean up, but leak some memory.
What is the correct way to pass a slot into a function to use multiple times? Any help would be appreciated.
Thanks,
Chris
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我很确定这是一个错误。如果您将其折叠为一个小示例,例如:
并跟踪分配,您会发现在行分配了一个对象(boost::signals::detail::signal_base_impl::iterator)
boost/lib/signals/src/signal_base.cpp
的 75 部分未释放。在第一个
connect
上,此迭代器附加到一个新的连接对象,其中signal_data
为 NULL:但是,在第二个
connect
上,相同连接对象被复用,同一行盲目覆盖原来的指针值。第二个对象已清理,但第一个对象尚未清理。作为验证,
signal_base_impl::slot_disconnected
中的断点(唯一清理signal_data
的地方)仅触发一次。我在 1.39.0 中找到了这个,但看起来在 1.40.0 中也是一样的。
您可以修改 boost::signals::detail::signal_base_impl::connect_slot 来清理它在现有连接的 signal_data 字段中找到的任何先前的迭代器值,如果您我们很乐意进行这样的更改并运行 Boost 的自定义构建。
最好确保您只设置固定次数,并忍受一些小的内存泄漏,您知道这些泄漏不会随着时间的推移而增加。
更新:
我本来打算将其提交给 Boost bug 跟踪器,但它已经在那里了。然而,这是一个小得多的测试用例。
https://svn.boost.org/trac/boost/ticket/738
3年前开业,未分配任何里程碑:-[
I'm pretty sure it's a bug. If you collapse it down to a tiny example, e.g.:
and trace the allocations, you'll find that one object (a
boost::signals::detail::signal_base_impl::iterator
) allocated at line 75 ofboost/lib/signals/src/signal_base.cpp
is not freed up.On the first
connect
, this iterator is attached to a fresh connection object, wheresignal_data
is NULL:On the second
connect
, however, the same connection object is reused, and the same line blindly overwrites the original pointer value. The second object is cleaned up, but the first is not.As verification, a breakpoint in
signal_base_impl::slot_disconnected
, the only place wheresignal_data
is cleaned up, is only triggered once.I tracked this down in 1.39.0, but it looks like it's the same in 1.40.0.
You could modify
boost::signals::detail::signal_base_impl::connect_slot
to clean up any previous iterator value it finds in thesignal_data
field of an existing connection, if you're comfortable making such a change and running a custom build of Boost.It might be better to just make sure you're only setting these up a fixed number of times and live with a few small memory leaks that you know won't grow over time.
Update:
I was going to submit this to the Boost bug tracker, but it's already there. This is a much smaller test case, however.
https://svn.boost.org/trac/boost/ticket/738
Opened 3 years ago, not assigned to any milestone :-[
为了供其他人参考,我很幸运地维护了自己的
signal_data
副本,并在删除信号之前将其删除。不知道有什么副作用,YMMV。像这样的东西:
For other people's reference, I am having some luck maintaining my own copy of
signal_data
, and deleting it before deleting the signal. Don't know of any side effects, YMMV.Something like this: