Ios 知道所有回调都是在libevent和bufferevent_空闲的情况下运行的

Ios 知道所有回调都是在libevent和bufferevent_空闲的情况下运行的,ios,c,sockets,libevent,Ios,C,Sockets,Libevent,我正在使用libevent 2.0.22版做一些工作,我正在努力处理bufferevent\u free并确保套接字在正确的时间关闭。这是在iOS 8.4上运行的使用Xcode 6.4构建的iOS应用程序中实现的 每个套接字都由一个struct bufferevent管理,我还有一个数据结构,用于跟踪该套接字的应用程序状态: bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_socket_co

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

每个套接字都由一个
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\u OPT\u CLOSE\u创建了它,所以我只是把它释放出来。然后我删除我正在使用的数据结构。看起来像这样:

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
之后触发的


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

是的,这是预期的libevent行为:在bufferevent_free()之后,它仍然可以调用回调。从libevent book:

Bufferevents是内部引用计数的,因此如果在释放bufferevent时它有挂起的延迟回调,则在回调完成之前不会删除它

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

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

这听起来很奇怪,
bufferevent\u free
在释放事件之前禁用所有事件并取消任何挂起的事件。是否还有其他事情(例如,这是多线程代码?您使用的是哪种libevent版本?)这是多线程代码,但我已经验证了对libevent的这些调用只发生在事件循环的线程上的回调中。我将为问题添加更多细节。使用更多细节编辑。同样获得与libevent 2.1.5相同的行为-betaI也必须调用evtimer_del(),但遗憾的是,在调用bufferevent_free(bev)后仍然获得超时回调;更重要的是,在调用event_base_free(base)。。。所以我还是得到了一份工作SIGSEVF@CodeAbominatorinsteal evtimer_del()尝试事件_del()。