知道所有回调都使用libevent和bufferevent_free运行



我正在使用libevent,版本2.0.22做一些工作,并且我正在努力处理bufferevent_free并确保套接字在正确的时间关闭。这是一个用Xcode 6.4构建的iOS应用程序,运行在iOS 8.4上。

每个套接字都由struct bufferevent管理,并且我还有一个数据结构来跟踪该套接字的应用程序状态:

bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_socket_connect_hostname(bev, dns_base, AF_UNSPEC, host, port_number);
struct stream_data *data = malloc(sizeof(struct stream_data));
/* initialize stream data here */
bufferevent_setcb(bev, read_cb, write_cb, event_cb, data);

在从其他缓冲区套接字回调时,我决定不需要刚才尝试打开的缓冲区。这发生在我在有问题的bev上获得连接回调之前。因为我用BEV_OPT_CLOSE_ON_FREE创建了它,我只是释放了它。然后我删除我正在使用的数据结构。如下所示:

bufferevent_free(bev);
free(stream_data); // the data corresponding to that bev
但是,在这种情况下,套接字实际上在此期间完成了连接。所以我的事件回调触发:
void event_cb(struct bufferevent *bev, short what, void *ctx)
{
    struct stream_data *data = ctx;
    // data now points to already freed memory
}

现在我有一个指针指向已经释放的内存。我已经用调试器断点,NSLog等确认事件回调在上面的free之后触发。

这是预期行为吗?如果是这样,我怎么知道我释放的缓冲事件已经完全消失了,从而可以安全地删除我自己的数据结构呢?

是的,这是预期的libeevent行为:在bufferevent_free()之后,它仍然可能调用你的回调。选自libevent book:

Bufferevents是内部引用计数的,所以当你释放它时,如果bufferevent有挂起的延迟回调,它将不会被删除,直到回调完成。

最简单的解决方案是在释放bufferevent对象之前删除所有回调:

bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
bufferevent_free(bev);

相关内容

  • 没有找到相关文章

最新更新