简体   繁体   English

C ++如何确保通过共享指针回收内存

[英]c++ how to make sure memory is reclaimed via shared pointers

I am using boost shared pointers and these pointers are really shared all over the application. 我使用的是Boost共享指针,而这些指针实际上在整个应用程序中都是共享的。 There are conditions, where such a shared pointer becomes invalid. 在某些情况下,此类共享指针将变为无效。 For example, a shared pointer to a network resource, that can become invalid because network became unavailable. 例如,指向网络资源的共享指针,由于网络不可用,该指针可能变得无效。 In such a scenario, where the shared pointer becomes invalid, i would like all objects to stop using it. 在这种情况下,共享指针变为无效,我希望所有对象停止使用它。 How can i send a message to all objects that the pointer is invalid. 我如何向所有对象发送消息,指出指针无效。 If it was a normal pointer, i could set it to null and all client code should be checking for null pointer before using it. 如果它是一个普通指针,我可以将其设置为null,并且所有客户端代码在使用它之前都应检查null指针。 But, in case of a shared pointer, which keeps reference count, how can i achieve similar functionality ? 但是,在使用共享指针的情况下,该指针保持引用计数,我如何实现类似的功能?

You can use weak pointers. 您可以使用弱指针。 That is, the code that handles the network events has the shared_ptr<Res> while everybody else has a weak_ptr<Res> . 也就是说,处理网络事件的代码具有shared_ptr<Res>而其他每个人都具有weak_ptr<Res> Now, 现在,

  • when the resource becomes unavailable, just reset the shared_ptr to NULL ; 当资源不可用时,只需将shared_ptr重置为NULL
  • when a client wants to use the resource, call lock() into the weak_ptr and test whether the returned shared_ptr is valid before using. 当客户端要使用资源时,请在使用前调用lock()weak_ptr并测试返回的shared_ptr是否有效。

If it was a normal pointer, i could set it to null and all client code should be checking for null pointer before using it. 如果它是一个普通指针,我可以将其设置为null,并且所有客户端代码在使用它之前都应检查null指针。

I doubt that. 我不信。 You'd then have copies of that raw pointer that point to invalid objects. 然后,您将具有指向无效对象的原始指针的副本。 You'd think that would solve the problem, but it doesn't . 您可能认为这可以解决问题,但事实并非如此 It amplifies it. 它放大了它。

The fact is that the shared pointer itself doesn't become invalid, the object it contains does. 事实是共享指针本身不会变得无效,共享指针本身会变为无效。 So, logically, whether it's still safe to use it should be contained in the object, not the shared pointer. 因此,从逻辑上讲,使用它是否仍然安全应该包含在对象中,而不是共享指针中。

a shared pointer to a network resource, that can become invalid because network became unavailable. 指向网络资源的共享指针,由于网络不可用,该指针可能变得无效。

Just throw an exception when you attempt to call a method that attempts to use the network... 当您尝试调用尝试使用网络的方法时,只需抛出异常即可。

You need to store more information. 您需要存储更多信息。 You could put the resource together with a bool in a tuple, or you could use boost::optional , and set it to none when you want to invalidate it. 您可以将资源和bool放到一个元组中,或者可以使用boost::optional ,并在要使其无效时将其设置为none

You almost certainly shouldn't be using shared pointer for this, since its semantics don't correspond to what you need. 您几乎可以肯定不应该为此使用共享指针,因为它的语义不符合您的需求。 Shared pointer implements a sort of poor man's garbage collection, where the object ceases to exist when there are no more pointers to it; 共享指针实现了一种穷人的垃圾回收,当不再有指向该对象的指针时,该对象将不复存在。 you need the opposite, that the pointers to the object cease to exist when there is no more object. 您需要相反,当没有更多对象时,指向该对象的指针将不复存在。 (A reverse garbage collection, so to speak.) (可以说是反向垃圾收集。)

I've used a ManagedPtr in the past; 我过去曾经使用过ManagedPtr the pointer registers itself with the object, which must derive from a ManagingObj class which sets the pointers to null in its destructor. 指针将向对象注册自己,该对象必须派生自ManagingObj类,该类在其析构函数中将指针设置为null。 This works sometimes, but it still doesn't remove entries from lists, etc. where the other objects may be keeping it. 有时这可行,但是它仍然不能从其他对象可能保留的列表等中删除条目。 And in practice, other objects which know about your network resource object may want to take specific actions when it disappears. 实际上,知道网络资源对象的其他对象在消失时可能希望采取特定的措施。 In the end, you almost always need to use the observer pattern: any object which acquires a pointer to your object registers with it to be notified in case of its demise. 最后,您几乎总是需要使用观察者模式:任何获取指向您对象的指针的对象都会向其注册,以防其死亡。

I would be inclined to follow the pattern used by standard streams: have an object that represents the resource, which can enter an error state and/or throw an exception when it detects (or is informed) that the network is no longer available. 我倾向于遵循标准流所使用的模式:有一个代表资源的对象,当它检测到(或被告知)网络不再可用时,它可以进入错误状态和/或引发异常。 If you can't change the existing resource class, then this new object can hold the existing resource object (that currently all your users have shared pointers to), and the users can share the new object. 如果您无法更改现有资源类,则此新对象可以保存现有资源对象(当前所有用户都具有共享的指针),并且用户可以共享新对象。

Unless you need all the users of this resource to respond promptly when it becomes unavailable, there doesn't seem any point trying to propagate a message to them all. 除非您需要该资源的所有用户在资源不可用时迅速做出响应,否则似乎没有任何必要尝试向所有人传播消息。 If you just want them to stop using it, they can do that the next time they try to use it, and discover that it doesn't work any more. 如果您只是想让他们停止使用它,则他们可以在下次尝试使用它时执行此操作,然后发现它不再起作用。 If they do really need a message, then write something to keep a list of them all, and call some function on them when the event that they're interested in occurs. 如果他们确实需要消息,则写一些东西来保存所有消息,并在他们感兴趣的事件发生时在它们上调用一些函数。 This is called the Observer pattern or "listeners", and armed with those search terms you can find implementations and alternatives. 这称为“观察者”模式或“侦听器”,并带有这些搜索词,您可以找到实现和替代方法。

Ideally, users should be able to check for the error state either as part of using the resource, or immediately afterwards. 理想情况下,用户应该能够在使用资源时或之后立即检查错误状态。 Testing before use is usually error-prone, since it creates a window in which the network perhaps could become unavailable after the test but before it's used. 使用前测试通常是容易出错的,因为它创建了一个窗口,其中的网络或许有可能成为测试后无法使用,但使用数据之前。 Once your code has to handle that case correctly you might as well make it the only case, by not bothering to check in advance. 一旦您的代码必须正确处理这种情况,您也可以通过不必事先检查来使它成为唯一的情况。

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

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