2010-11-04 106 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是一個自然的解決方案。