简体   繁体   English

Boost.thread可能的内存泄漏

[英]Boost.thread possible memory leak

Since I've started making a little project aiming to have a crossplatform support, I chose boost 1.47 to interact with the underlying OS. 由于我已经开始制作一个旨在提供跨平台支持的小项目,因此我选择了boost 1.47与底层操作系统进行交互。 My project needed some multithreading, so I made a little wrapper over boost threads to fulfill my needs. 我的项目需要一些多线程,因此我在boost线程上做了一些包装,以满足我的需求。

Little I knew, boost apparently leaves the thread on memory after destructing its object(?), or then it may have some sort of memory leak possibility. 我不知道,boost在破坏线程的object(?)之后显然将线程留在了内存中,否则它可能会出现某种内存泄漏的可能性。

The implementation of my wrapper has a scoped_ptr of type thread, and the scoped ptr will get initialized when one calls the start() function in the wrapper class. 我的包装器的实现具有类型为thread的scoped_ptr,并且在调用包装器类中的start()函数时将对有范围的ptr进行初始化。 The running thread will be stopped from main thread using thread->interrupt(), and the destructor will be called from the wrapper function. 运行线程将使用thread-> interrupt()从主线程停止,并且析构函数将从包装函数中调用。 (Destructor of the thread's procedure structure, which has operator()() in it. (线程的过程结构的析构函数,其中包含operator()()。

Here's the implementation of the wrapper class: (note: i_exception and couple of other functions are parts of other project components) 这是包装器类的实现:(注意:i_exception和其他几个功能是其他项目组件的一部分)

#define TIMED_JOIN boost::posix_time::milliseconds(1)

namespace utils
{
    struct thread_threadable
    {
        template<typename T> friend class ut_thread;
    private:
        boost::shared_ptr<thread_threadable> instance;
    public:
        virtual ~thread_threadable() {}
        virtual void operator()() = 0;
    };

    template<typename T = thread_threadable>
    class ut_thread
    {
    public:
        typedef T proc_t;
    private:
        boost::scoped_ptr<boost::thread> thr;
        boost::shared_ptr<proc_t> proc;
    public:
        explicit ut_thread(const boost::shared_ptr<proc_t> &procedure) : proc(procedure) {}
        ~ut_thread();

        void start();
        void stop();

        bool running() const {return this->thr.get() != NULL;}
        proc_t &procedure() const
        {
            BOOST_ASSERT(this->proc.get() != NULL);
            return *this->proc;
        }
    };
}
typedef utils::thread_threadable threadable;

template<typename T>
utils::ut_thread<T>::~ut_thread()
{
    if(this->thr.get() != NULL)
    {
        BOOST_ASSERT(this->proc.get() != NULL);
        this->stop();
    }
}
template<typename T>
void utils::ut_thread<T>::start()
{
    if(this->thr.get() != NULL)
        i_exception::throw_this("another thread of this procedure is already running");
    if(this->proc.get() == NULL)
        i_exception::throw_this("procedure object not initialized");

    this->proc->instance = this->proc;

    this->thr.reset(new boost::thread(boost::ref(*this->proc)));
    this->thr->timed_join(TIMED_JOIN);
}
template<typename T>
void utils::ut_thread<T>::stop()
{
    if(this->thr.get() == NULL)
        i_exception::throw_this("no thread was running");

    this->thr->interrupt();
    this->proc->~T();
    this->thr.reset(NULL);
}

And then by checking the functionality of this wrapper class, I made test to main.cpp: 然后通过检查此包装器类的功能,我对main.cpp进行了测试:

struct my_thr : public utils::thread_threadable
{
    void operator()()
    {
        while(true);
    }
};

int main()
{
    while(true)
    {
        utils::ut_thread<> thr(boost::shared_ptr<threadable>(new my_thr));
        utils::ut_thread<> thr1(boost::shared_ptr<threadable>(new my_thr));
        thr.start();
        thr1.start();
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
    return 0;
}

At which point I noticed that these threads do not destruct, they will stay in memory until program gets terminated. 在这一点上,我注意到这些线程不会破坏,它们将保留在内存中,直到程序终止。 They also keep executing the 'while(true)' statement. 他们还继续执行“ while(true)”语句。

So I'm asking, what would cause this kind of behaviour? 所以我在问,什么会导致这种行为? Is it something defined, or just a bug or something else? 它是定义的东西,还是一个错误或其他东西?

First of all interrupt will only stop the thread at certain ìnterruption points (taken from boost::threads documentation, slightly reformated): 首先, interrupt只会在某些“中ìnterruption points处停止线程(取自boost::threads文档,略有修改):

Predefined Interruption Points 预定义的中断点

The following functions are interruption points, which will throw boost::thread_interrupted if interruption is enabled for the current thread, and interruption is requested for the current thread: 以下函数是中断点,如果当前线程启用了中断,并且请求了当前线程的中断,则它们将引发boost :: thread_interrupted:

 boost::thread::join() boost::thread::timed_join() boost::condition_variable::wait() boost::condition_variable::timed_wait() boost::condition_variable_any::wait() boost::condition_variable_any::timed_wait() boost::thread::sleep() boost::this_thread::sleep() boost::this_thread::interruption_point() 

Since you don't have any of those in your thread execution calling interrupt() on it should have no effect. 由于您的线程执行中没有任何对象,因此在其上调用interrupt()应该无效。

Now for destroying the thread : 现在要销毁thread

~thread(); 〜thread();

Effects: If *this has an associated thread of execution, calls detach(). 效果:如果*这具有关联的执行线程,则调用detach()。 Destroys *this. 销毁*这个。

Throws: Nothing. 抛出:没事。

The timed_join() you called on the thread should fail, since the thread won't have finished it's execution that fast. 您在线程上调用的timed_join()应该会失败,因为线程不会完成那么快的执行。 Therefore you didn't join (or detach , but that wouldn't change the ultimate outcome) your threads, meaning they do have an associated thread of execution when they are destroyed. 因此,您没有join (或detach ,但不会改变最终结果)您的线程,这意味着它们在销毁时确实具有关联的执行线程 Therefore they are detached, meaning that they will run till they are finished even through they are no longer controllable through the boost::thread object. 因此,它们是分离的,这意味着它们将一直运行到完成为止,即使它们不再可以通过boost::thread对象控制。 Since they are executing and infinite loop, finishing their execution might take some time so to say. 因为他们正在执行无限循环,所以可以说完成他们的执行可能要花一些时间。

As a Sidenote: if you choose to change to C++11 std::threads later, you should note that destroying those without manually calling join() or detach() is not valid code. 附带说明:如果您以后选择更改为C ++ 11 std::threads ,则应注意在不手动调用join()detach()情况下销毁它们是无效的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM