【问题标题】:Boost.thread possible memory leakBoost.thread 可能的内存泄漏
【发布时间】:2012-01-15 14:22:38
【问题描述】:

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

我几乎不知道,boost 显然在销毁其对象(?)后将线程留在内存中,或者它可能有某种内存泄漏的可能性。

我的包装器的实现有一个 thread 类型的 scoped_ptr,当调用包装器类中的 start() 函数时,作用域 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)' 语句。

所以我在问,什么会导致这种行为?它是定义了什么,还是只是一个错误或其他什么?

【问题讨论】:

  • 我真的不明白你的代码在做什么,但没有shared_ptr 循环吗?
  • 我检查了shared_ptr的有效性,应该没问题

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


【解决方案1】:

首先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()on 它应该没有效果。

现在销毁thread

~线程();

效果:如果 *this 有关联的执行线程,则调用 detach()。销毁 *this。

抛出:什么都没有。

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

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

【讨论】:

  • 谢谢,代码现在可以正常工作了!认为我应该更仔细地阅读文档:)
  • 大声笑@“由于它们正在执行并且无限循环,因此可以说完成它们的执行可能需要一些时间。” +1
猜你喜欢
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多