在C ++ 11中释放动态分配的uv_timer_t(libuv)实例

时间:2013-10-16 13:02:43

标签: c++ c++11 memory-leaks dynamic-allocation event-loop

我有一个需要将任务安排到libuv事件循环的函数。我的想法是创建一个0ms超时的计时器。我尝试了以下代码:

void myFunction() {
    ...
    uv_timer_t* timer = new uv_timer_t();
    uv_timer_init(uv_default_loop(), timer);
    uv_timer_start(timer, [&](uv_timer_t* timer, int status) {
        // Scheduled task
    }, 0, 0);
}

这种方法运行良好,但问题是,永远不会释放动态分配的计时器。我已经尝试在回调中释放计时器,但这导致了分段错误:

void myFunction() {
    ...
    uv_timer_t* timer = new uv_timer_t();
    uv_timer_init(uv_default_loop(), timer);
    uv_timer_start(timer, [&](uv_timer_t* timer, int status) {
        // Scheduled task
        delete timer;
    }, 0, 0);
}

我还试图在实际内存释放之前调用uv_timer_stop(timer);uv_unref((uv_handle_t*) timer);,但分段错误仍然会重新发生。

2 个答案:

答案 0 :(得分:8)

我遇到了同样的问题,这就是你处理它的方式:

首先,您需要为计时器句柄关闭时创建一个回调:

void on_timer_close_complete(uv_handle_t* handle)
{
    free(handle);
}

请注意,句柄将在回调中释放。

当你停下来并释放你的计时器时,你会这样做:

uv_timer_stop(pTimerHandle);
uv_close((uv_handle_t *)pTimerHandle,on_timer_close_complete);

不直观的部分是uv_close()电话。我认为我在文档中的任何地方都没有看到它。我只能通过关注来源来解决这个问题。

这样,libuv会在完成计时器后执行你的回调,然后你可以在回调中安全地释放它。

答案 1 :(得分:1)

根据@IntelliAdmin的答案,如果您不想自己关闭它,只是希望在没有更多引用时将其关闭,您可以使用智能指针:

template<typename T>
using deleted_unique_ptr = std::unique_ptr<T, std::function<void( T* )>>;


deleted_unique_ptr<uv_timer_t> timer = deleted_unique_ptr<uv_timer_t>( new uv_timer_t, [&]( uv_timer_t *timerhandl ) {
    uv_close( reinterpret_cast<uv_handle_t *>( timerhandl ), OnTimerClose );
});

然后对于回调,只需删除指针:

void OnTimerClose( uv_handle_t *handle )
{
    delete handle;
}