2010-11-04 50 views
4

我最近开始使用boost。到目前为止,大部分事情都非常简单。但是有一件事令我感到不快,就是shared_ptr在整个提升过程中的泛滥。即使在一些简单的例子中,也使用了shared_ptr。boost asio和shared_ptrs的扩散

所以我的问题是,如果我使用boost来接受tcp连接,然后处理它们。只要我保证在堆上创建的对象(boost :: asio :: ip :: tcp :: socket,以及将为异步方法调用的类)将不会被删除,直到我完成使用tcp ,那么我不需要shared_ptr正确?

我写了一个简单的tcp服务器和客户端,不使用共享ptr,它的工作原理。但是我只想要一些外界的确认,我的评估是正确的。

另外,在你的经验中,你有没有一个需要使用shared_ptr安抚升压?

+0

如果你将代码上传到某处,或许作为github的要点(http://gist.github.com),那么对你的尝试发表评论会更容易。 – 2010-11-04 19:01:25

+0

@Daniel:谢谢你指出gist.github.com,从来不知道它。当我有机会的时候我会提出一些问题。 – anio 2010-11-05 14:59:16

回答

6

阅读documentationio_service

破坏序列描述 上述允许程序通过使用 shared_ptr的<>简化 其资源管理。其中一个对象的 寿命被联系在一个 连接(或 异步操作的一些其他序列),一个shared_ptr 到对象的生命周期将被绑定到 处理程序与它相关联的所有异步 操作。这 工作如下:

当单个连接结束时,所有 关联的异步操作 完成。相应的处理程序对象被销毁,并且所有 shared_ptr对对象 的引用都被销毁。

要关闭整个 程序。该io_service功能 停止()作为呼吁尽快终止任何 的run()的调用。 上面定义的io_service析构函数销毁所有处理程序,导致所有 shared_ptr引用连接对象的所有 被销毁。

换句话说,使用shared_ptr而不是裸指针将会成倍地更容易。

+0

我几乎没有使用asio的经验,但似乎如果io_service有一个函数“stop_and_delete_me”可以从一个处理程序中调用,那么我看不到这个shared_ptr的东西会成为问题。然后它可以像这样轻松关闭io_service.post([&](){cleanup_my_resources(); io_service.stop_and_delete_me()});由于清理资源是在处理程序中完成的,因此不存在任何问题。由于stop_and_delete_me保证没有更多的处理程序被调用,这也不是问题。这样做的巨大优势是代码是确定性的。 shared_ptr不是确定性的。 – user239558 2013-03-14 11:59:52

1

shared_ptr或类似的东西(vectorauto_ptr等)是维护异常安全所必需的。当你将一个delete调用放到你的代码中时,可能会抛出一个异常,这会导致删除跳过内存泄漏。

如果您使用的是所有堆栈分配的对象,并且可以这样做,那么一定要这么做。我猜想你所看到的大多数shared_ptr的原因是因为有人想要存储具有多态行为的对象,并且不希望受制于切片问题。

+0

咦?上次我检查删除不会引发异常。我从来没有发生过这种事。也许如果你尝试删除垃圾的东西会爆炸。假设delete引发了一个异常,当引用计数达到零时,shared_ptr在试图删除时会爆炸。但是,正如我所说的,我自己在管理记忆,并且正确地做到这一点。另外,当你说shared_ptr避免了切片问题时,我不明白你的意思。怎么样? – anio 2010-11-05 12:43:51

+0

@anio:不 - 删除本身不是导致问题的原因。问题是在调用'new'和调用'delete'之间的任何时候都可能抛出异常。当抛出异常时(在新调用和删除调用之间),对delete的调用永远不会发生,因此你已经泄漏了内存。将指针放入某种受控容器的形式可以确保在发生抛出的异常时解除堆栈时删除内存。 – 2010-11-05 12:59:38

0

引用计数是执行异步操作所固有的。否则无法知道对象何时不再使用。您可以通过维护自己的引用计数来避免shared_ptr。但是你会大大地重新实现同样的事情。这里的问题不是shared_ptr,而是你对此的态度。您应该简单地接受引用计数对于异步代码是必需的,因此shared_ptr是一个自然的解决方案。