1

我正在调试这个数据库项目。它为更高级别的应用程序包装了对 SQLite 的访问。它被设计为异步运行,也就是说,它具有 ExecuteRequestAsync() 和 IsRequestReady() 等方法。当调用 ExecuteRequestAsync 时,它会产生一个 boost::thread 来完成这项工作并立即返回该函数。当更高级别的应用程序决定它不再想要运行请求的结果时,它可以调用 DumpRequest() 来取消它。由于很难优雅地取消数据库请求,因此 DumpRequest 的实现只是维护一个“清理监视器线程”,等待“完成的请求”并删除它们。所有 boost::threads 都通过 boost::shared_ptr 进行管理,例如:

boost::shared_ptr<boost::thread> my_thread = new boost::thread(boost::bind(&DBCon::RunRequest, &this_dbcon));

当不再需要(被取消)时:

vector<boost::shared_ptr<boost::thread> > threads_tobe_removed;
// some iteration
threads_tobe_removed[i].get()->join();
threads_tobe_removed.erase(threads_tobe_removed.begin()+i);

我创建了这个单元测试项目来测试执行和转储请求的机制。它运行请求并随机取消正在运行的请求,并重复数千遍。结果证明机制没问题。一切都按预期工作。

但是通过sysinternal的Process Explorer观察单元测试项目,发现有句柄泄漏问题。每 500 次通过,句柄计数增加 1,并且永远不会返回。增加的是“事件”类型的句柄。文件和线程句柄没有增加(当然,随着线程的产生,句柄的数量也在增加,但是每一百次调用 Sleep(10000) 以等待它们被清理,以便可以观察到句柄计数)。

我自己没有管理事件句柄。它们是由 boost::thread 在创建线程时创建的。我只保证优雅地关闭线程,我不知道事件的用途。

我想知道是否有人遇到过类似的问题?这种泄漏的原因可能是什么?Process Explorer 中的这个数字是否足够可靠,可以称之为句柄泄漏?有没有办法追踪和修复它?

我在 Windows Vista 上使用静态链接的 boost 1.40 和 Visual C++。

4

1 回答 1

1

访问threads_tobe_removed线程安全吗?如果不是,则可能存在竞争条件,即一个线程通过调用向向量添加一个线程DumpRequest,而清理监视器线程从向量中删除一个线程。因此,boost::thread-objects 可能会在没有先加入线程的情况下被销毁,这将使线程在没有关联对象的情况下运行,这可能解释了泄漏。

于 2009-11-16T11:46:05.357 回答