C++ 创建&;时是否可以使用boost::shared\u ptr;在boost::asio异步模式下接受套接字?

C++ 创建&;时是否可以使用boost::shared\u ptr;在boost::asio异步模式下接受套接字?,c++,boost-asio,shared-ptr,C++,Boost Asio,Shared Ptr,对不起,如果我不能给我的问题加一个更好的标题。 我正在调试我的程序,这时我发现了一些非常有趣的事情。代码非常简单。请关注我的评论: //my session class class Session { public: /// Constructor. Session(boost::asio::io_service &io_service) : socket_(io_service) { } boost::asio::ip::tcp::socket&

对不起,如果我不能给我的问题加一个更好的标题。 我正在调试我的程序,这时我发现了一些非常有趣的事情。代码非常简单。请关注我的评论:

//my session class
class Session
{
public:
  /// Constructor.
  Session(boost::asio::io_service &io_service)
    : socket_(io_service)
  {
  }

  boost::asio::ip::tcp::socket& socket()
  {
    return socket_;
  }

void async_read(/*...*/);
void async_write(/*...*/);
//blah blah
private:
std::vector<char> inbound_data_;//<---note this variable, but don't mind it until i tell you
std::string outbound_data_;
boost::asio::ip::tcp::socket socket_;
}

typedef boost::shared_ptr<Session> session_ptr; //just for easy reading


//and this is my connection server class
class ConnectionServer {
public:
void ConnectionServer::CreatSocketAndAccept() {
    session_ptr new_sess(new Session(io_service_));//<--I created a scope limited shared_ptr
    Print()<< "new_sess.use_count()= " << new_sess.use_count() << std::endl;//prints 1
    acceptor_.async_accept(new_sess->socket(),//<-used it for async connection acceptance
            boost::bind(&ConnectionServer::handle_accept, this,
                    boost::asio::placeholders::error, new_sess));
   Print()<< "new_sess.use_count()= " << new_sess.use_count() << std::endl;//prints 2
}//<-- Scope is ending. what happens to my new_sess? who keeps a copy of my session?

//and now the strangest thing:
void ConnectionServer::handle_accept(const boost::system::error_code& e, session_ptr sess) {
    if (!e) {

        Print()<< "sess.use_count()= " << sess.use_count() << std::endl;//prints 4 !!!! while I have never copied the session anywhere else in between
        Print() << "Connection Accepted" << std::endl;
        handleNewClient(sess);
    }
    else
    {
        std::cout << "Connection Refused" << std::endl;
    }
    CreatSocketAndAccept();
} 
有些时候:

Basic Debug [C/C++ Application] 
    SimMobility_Short [10350] [cores: 0]    
        Thread [1] 10350 [core: 0] (Suspended : Signal : SIGSEGV:Segmentation fault)    
            malloc_consolidate() at malloc.c:4,246 0x7ffff5870e20   
            malloc_consolidate() at malloc.c:4,215 0x7ffff5871b19   
            _int_free() at malloc.c:4,146 0x7ffff5871b19    
            __gnu_cxx::new_allocator<char>::deallocate() at new_allocator.h:100 0xa4ab4a    
            std::_Vector_base<char, std::allocator<char> >::_M_deallocate() at stl_vector.h:175 0xab9508    
            std::_Vector_base<char, std::allocator<char> >::~_Vector_base() at stl_vector.h:161 0xabf8c7    
            std::vector<char, std::allocator<char> >::~vector() at stl_vector.h:404 0xabeca4    
            sim_mob::Session::~Session() at Session.hpp:35 0xabea8d 
            safe_delete_item<sim_mob::Session>() at LangHelpers.hpp:136 0xabef31    
            sim_mob::ConnectionHandler::~ConnectionHandler() at ConnectionHandler.cpp:40 0xabd7e6   
            <...more frames...> 
    gdb
Basic Debug [C/C++ Application] 
    SimMobility_Short [10498] [cores: 1]    
        Thread [1] 10498 [core: 1] (Suspended : Signal : SIGSEGV:Segmentation fault)    
            _int_free() at malloc.c:4,076 0x7ffff5871674    
            std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() at 0x7ffff639d540   
            sim_mob::ConnectionHandler::~ConnectionHandler() at ConnectionHandler.cpp:30 0xabd806   
            boost::checked_delete<sim_mob::ConnectionHandler>() at checked_delete.hpp:34 0xadd482   
            boost::detail::sp_counted_impl_p<sim_mob::ConnectionHandler>::dispose() at sp_counted_impl.hpp:78 0xadd6a2  
            boost::detail::sp_counted_base::release() at sp_counted_base_gcc_x86.hpp:145 0x849d5e   
            boost::detail::shared_count::~shared_count() at shared_count.hpp:305 0x849dd7   
            boost::shared_ptr<sim_mob::ConnectionHandler>::~shared_ptr() at shared_ptr.hpp:164 0x84a668 
            sim_mob::ClientHandler::~ClientHandler() at ClientHandler.cpp:42 0xac726d   
            sim_mob::ClientHandler::~ClientHandler() at ClientHandler.cpp:45 0xac72da   
            <...more frames...> 
    gdb 
Basic调试[C/C++应用程序]
simu-Short[10498][cores:1]
线程[1]10498[core:1](挂起:信号:SIGSEGV:分段错误)
_malloc.c处的int_free():4076 0x7ffff5871674
std::basic_string::~basic_string()位于0x7ffff639d540
sim_mob::ConnectionHandler::~ConnectionHandler()位于ConnectionHandler.cpp:30 0xabd806
boost::checked_delete()位于checked_delete.hpp:34 0xadd482
boost::detail::sp_counted_impl_p::dispose()位于sp_counted_impl.hpp:78 0xadd6a2
boost::detail::sp_counted_base::release()位于sp_counted_base_gcc_x86.hpp:145 0x849d5e
boost::detail::shared_count::~shared_count()位于shared_count处。hpp:305 0x849dd7
boost::shared_ptr::~shared_ptr()位于shared_ptr.hpp:164 0x84a668
sim_mob::ClientHandler::~ClientHandler()位于ClientHandler.cpp:42 0xac726d
sim_mob::ClientHandler::~ClientHandler()位于ClientHandler.cpp:45 0xac72da
gdb

这是否意味着我的记忆已经被破坏了?我怎样才能做更多的检查?谢谢你

这句话是魔术的寓意:

acceptor_.async_accept(new_sess->socket(),//<-used it for async connection acceptance
        boost::bind(&ConnectionServer::handle_accept, this,
                boost::asio::placeholders::error, new_sess));

acceptor.async\u accept(new\u sess->socket(),//这一行是魔术的所在:

acceptor_.async_accept(new_sess->socket(),//<-used it for async connection acceptance
        boost::bind(&ConnectionServer::handle_accept, this,
                boost::asio::placeholders::error, new_sess));

acceptor\uu.async\u accept(新的sess->socket(),//您应该能够使用
shared\u ptr
,这样,我就可以以相同的方式使用它,而不会出现问题

在内部,asio会保留一份
共享\u ptr
(通过boost::bind)的副本,直到它调用
handle\u accept
。这就是允许您首先传递
共享\u ptr
的原因。如果您没有将其作为参数之一添加,那么它会在对象在您创建的函数中确定范围后立即清理对象


我怀疑您还有其他未定义的行为,使用原始指针无法发现。

您应该能够以这种方式使用
shared\u ptr
,我以相同的方式使用它,不会出现问题

在内部,asio会保留一份
共享\u ptr
(通过boost::bind)的副本,直到它调用
handle\u accept
。这就是允许您首先传递
共享\u ptr
的原因。如果您没有将其作为参数之一添加,那么它会在对象在您创建的函数中确定范围后立即清理对象

我怀疑您还有其他未定义的行为,使用原始指针无法发现。

To(尝试)回答第二个问题:您似乎在对会话发出双重删除。只有从原始指针创建第二个作用域\u ptr时,才可能执行此操作。这是您不应该执行的操作。您是否将会话的原始指针传递给任何反过来创建其作用域ptr的函数

您可以尝试让会话继承启用来自此的\u共享\u。这将解决此问题,因为任何原始指针都使用相同的作用域\u ptr计数器。但您不应将此视为真正的解决方案。真正的解决方案是消除多个作用域\u ptr实例

编辑:添加了另一种调试可能性

您还可以尝试在会话的析构函数中设置断点,并查看第一次/第二次删除的回溯回答第二个问题:您似乎在对会话发出双重删除。只有从原始指针创建第二个作用域\u ptr时,才可能执行此操作。这是您不应该执行的操作。您是否将会话的原始指针传递给任何反过来创建其作用域ptr的函数

您可以尝试让会话继承启用来自此的\u共享\u。这将解决此问题,因为任何原始指针都使用相同的作用域\u ptr计数器。但您不应将此视为真正的解决方案。真正的解决方案是消除多个作用域\u ptr实例

编辑:添加了另一种调试可能性

您还可以尝试在会话的析构函数中设置断点,并查看第一次/第二次删除的回溯。

如本文所述,可以将共享指针与Boost.Asio的async_*函数一起使用


根据调用堆栈和行为,看起来至少有一个资源被删除了两次。是否有可能通过原始指针和
共享\u ptr
管理
会话

使用boost::shared\u ptr进行管理

void ConnectionServer::CreatSocketAndAccept() {
  session_ptr new_sess(new Session(io_service_)); // shared pointer
  ...
}
使用原始指针进行管理:

sim_mob::Session::~Session()
safe_delete_item<sim_mob::Session>() // raw pointer
sim_mob::ConnectionHandler::~ConnectionHandler()

作为旁注,一个常见的习惯用法是让
Session
从继承。它允许
Session
在异步调用链的整个过程中保持活动状态,方法是将共享指针作为句柄传递给实例来代替它。例如,它允许
Session
在异步调用链中保持活动状态nchronous read操作非常出色,只要this()
中的
shared\u的结果被绑定为
会话::异步\u read
回调的实例句柄。

如本文所述,可以将共享指针与Boost.Asio的异步函数一起使用


根据调用堆栈和行为,看起来至少有一个资源被删除了两次。是否有可能通过原始指针和
共享\u ptr
管理
会话

使用boost::shared\u ptr进行管理

void ConnectionServer::CreatSocketAndAccept() {
  session_ptr new_sess(new Session(io_service_)); // shared pointer
  ...
}
使用原始指针进行管理:

sim_mob::Session::~Session()
safe_delete_item<sim_mob::Session>() // raw pointer
sim_mob::ConnectionHandler::~ConnectionHandler()

作为旁注,一个常见的习惯用法是让
会话
从继承。它允许
会话
在其异步调用链的整个过程中保持活动状态,方法是将共享指针作为句柄传递给实例,以代替此。例如,它允许