【问题标题】:Freeing dynamically allocated uv_timer_t (libuv) instance in C++11在 C++11 中释放动态分配的 uv_timer_t (libuv) 实例
【发布时间】:2013-10-24 14:41:51
【问题描述】:

我有一个需要将任务安排到 libuv 事件循环的函数。我的想法是创建一个超时时间为 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
    }, 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);,但分段错误仍然存​​在。

【问题讨论】:

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


    【解决方案1】:

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

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

    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 将在计时器完成后执行您的回调,然后您可以在该回调中安全地释放它。

    【讨论】:

    • 谢谢。我有同样的问题。但是文档清楚地表达了这一点。 docs.libuv.org/en/v1.x/handle.html?highlight=uv_close 并且 doc 必须大写。我从来没有注意到它。这也是真实的示例代码在使用 uv_timer_t 时没有显示 uv_close
    • @BernardoRamos documentation for the base handle type 仍然这么说,并明确提到了内存释放。 timer docs 中没有关于它不适用的任何内容。是文档错误吗?如果这仍然是释放内存的方法,你会这样做吗?空闲任务?
    【解决方案2】:

    根据@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;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-20
      • 1970-01-01
      • 2021-03-27
      • 2013-11-22
      • 2023-03-03
      • 2010-12-05
      • 2018-09-01
      • 2017-06-13
      相关资源
      最近更新 更多