Qihoo360 / evpp

A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

shared_ptr circular reference problem

Snape3058 opened this issue · comments

The function InvokeTimer::Create will actually trigger a shared_ptr circular reference that makes an object of InvokeTimer to hold its own shared_ptr. If InvokeTimer::OnTimeTriggered or InvokeTimer::OnCancled is not finally invoked, it will probably lead to a memory leak.

According to issue #110 it seems that it could probably trigger some real memory leaks under some circumstances.

If you do this on purpose, could you please explain your ideas? And if you think it could be a problem, just simply reply to this issue to confirm our report.

Thank you.

This is the bug report generated by my static analyzer:

evpp/invoke_timer.cc:26:5: warning: Circular reference will lead to memory leak
    it->self_ = it;
    ^~~~~~~~~~~~~~

Events:
evpp/invoke_timer.cc:25:56: note: Calling 'move<std::function<void ()> &>'
    InvokeTimerPtr it(new InvokeTimer(evloop, timeout, std::move(f), periodic));
                                                       ^~~~~~~~~~~~
evpp/invoke_timer.cc:25:56: note: Returning from 'move<std::function<void ()> &>'
    InvokeTimerPtr it(new InvokeTimer(evloop, timeout, std::move(f), periodic));
                                                       ^~~~~~~~~~~~
evpp/invoke_timer.cc:25:27: note: Calling constructor for 'InvokeTimer'
    InvokeTimerPtr it(new InvokeTimer(evloop, timeout, std::move(f), periodic));
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
evpp/invoke_timer.cc:14:50: note: Calling 'move<std::function<void ()> &>'
    : loop_(evloop), timeout_(timeout), functor_(std::move(f)), periodic_(periodic) {
                                                 ^~~~~~~~~~~~
evpp/invoke_timer.cc:14:50: note: Returning from 'move<std::function<void ()> &>'
    : loop_(evloop), timeout_(timeout), functor_(std::move(f)), periodic_(periodic) {
                                                 ^~~~~~~~~~~~
evpp/invoke_timer.cc:14:41: note: Calling move constructor for 'function<void ()>'
    : loop_(evloop), timeout_(timeout), functor_(std::move(f)), periodic_(periodic) {
                                        ^~~~~~~~~~~~~~~~~~~~~~
evpp/invoke_timer.cc:14:41: note: Returning from move constructor for 'function<void ()>'
    : loop_(evloop), timeout_(timeout), functor_(std::move(f)), periodic_(periodic) {
                                        ^~~~~~~~~~~~~~~~~~~~~~
evpp/invoke_timer.cc:25:27: note: Returning from constructor for 'InvokeTimer'
    InvokeTimerPtr it(new InvokeTimer(evloop, timeout, std::move(f), periodic));
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
evpp/invoke_timer.cc:25:23: note: Allocate memory object: [Newed] HeapSymRegion{conj_$1{class evpp::InvokeTimer *, LC1, S1906113, #1}}
    InvokeTimerPtr it(new InvokeTimer(evloop, timeout, std::move(f), periodic));
                      ^
evpp/invoke_timer.cc:26:5: note: Pointer assignment: class std::shared_ptr<class evpp::InvokeTimer> HeapSymRegion{conj_$1{class evpp::InvokeTimer *, LC1, S1906113, #1}}->self_ = HeapSymRegion{conj_$1{class evpp::InvokeTimer *, LC1, S1906113, #1}} (pointer in the reference loop)
    it->self_ = it;
    ^
evpp/invoke_timer.cc:26:5: note: Circular reference will lead to memory leak
    it->self_ = it;
    ^~~~~~~~~~~~~~