Boost.thread可能的内存泄漏

时间:2012-01-15 14:22:38

标签: c++ multithreading memory-leaks boost-thread

由于我已经开始制作一个旨在获得跨平台支持的小项目,我选择了boost 1.47来与底层操作系统进行交互。我的项目需要一些多线程,所以我在boost线程上做了一个小包装来满足我的需求。

我知道的很少,在破坏对象(?)之后,boost显然会将线程留在内存中,或者它可能会有某种内存泄漏的可能性。

我的包装器的实现有一个类型为thread的scoped_ptr,当一个调用包装类中的start()函数时,scoped ptr将被初始化。使用thread-> interrupt()从主线程停止正在运行的线程,并从包装函数调用析构函数。 (线程的过程结构的析构函数,其中包含operator()()。

这是包装类的实现: (注意: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);
}

然后通过检查这个包装类的功能,我对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;
}

此时我注意到这些线程没有被破坏,它们将保留在内存中,直到程序终止。他们还继续执行'while(true)'语句。

所以我问,这会导致什么样的行为?是定义了什么,还是只是一个bug或其他东西?

1 个答案:

答案 0 :(得分:3)

首先interrupt只会停止特定ìnterruption points的帖子(取自boost::threads文档,稍加重新格式化):

  

预定义中断点

     

以下功能是中断点,将抛出   如果为当前启用中断,则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()

由于你的线程执行中没有任何一个调用它interrupt()应该没有效果。

现在要销毁thread

  

〜螺纹();

     

效果:如果*这有一个关联的执行线程,则调用detach()。摧毁*这个。

     

投掷:没什么。

你调用线程的timed_join()应该失败,因为线程不会快速完成它的执行。因此,您没有join(或detach,但这不会改变最终结果)您的线程,这意味着它们确实具有关联的执行线程销毁。因此它们是分离的,意味着它们将一直运行直到它们完成,即使它们不再通过boost::thread对象可控制。由于它们正在执行并且无限循环,因此完成它们的执行可能需要一些时间来说。

作为旁注:如果您稍后选择更改为C ++ 11 std::threads,则应注意,在未手动调用join()detach()的情况下销毁这些代码不是有效代码。< / p>