Domanda

Per qualche motivo questo si traduce in una violazione di accesso, tuttavia non avendo alcuna documentazione / aiuto dettagliati su questo non sono sicuro di dove stia sbagliando. Da quando ho seguito ciò che ho visto sul sito boost, questo dovrebbe essere corretto e stampare il contenuto di ogni chiamata asio :: write dal client su una nuova linea. Il client sembra funzionare bene. Anche se al momento il server si arresta in modo anomalo, ma non ha ancora inviato nulla.

La violazione di accesso si verifica in basic_stream_socket.hpp alla riga 275. La causa sembra essere che l'oggetto (boost :: asio :: stream_socket_service) non sia inizializzato (il valore di questo puntatore è 0xfeeefeee), tuttavia non capisco perché non lo è.

L'output dei programmi:

  

Avvia il server
  Server :: startAccept ()
  Server :: handleAccept ()
  Connessione accettata
  Collegamento :: startRead ()
  Server :: startAccept ()
  Collegamento :: handleRead ()
  READ ERROR: l'operazione di I / O è stata interrotta a causa della chiusura di un thread o di una richiesta dell'applicazione
  Connection :: startRead ()

Il codice

#include "precompiled.h"
#include "db.h"
class Connection
    : public boost::enable_shared_from_this<Connection>
{
public:
    typedef boost::shared_ptr<Connection> Pointer;

    static Pointer create(boost::asio::io_service& ioService)
    {
        return Pointer(new Connection(ioService));
    }

    ip::tcp::socket& getSocket()
    {
        return socket;
    }

    void startRead()
    {
        std::cout << "Connection::startRead()" << std::endl;
        socket.async_read_some(boost::asio::buffer(readBuffer),
            boost::bind(&Connection::handleRead,this,_1,_2));
    }
private:
    Connection(asio::io_service& ioService)
        : socket(ioService)
    {
    }

    void handleWrite(const boost::system::error_code&,size_t)
    {
    }
    void handleRead(const boost::system::error_code&error,size_t len)
    {
        std::cout << "Connection::handleRead()" << std::endl;
        if(error)
        {
            std::cout << "READ ERROR: ";
            std::cout << boost::system::system_error(error).what();
            std::cout << std::endl;
        }
        else
        {
            std::cout << "read: ";
            std::cout.write(readBuffer.data(),len);
            std::cout << std::endl;
        }
        startRead();
    }
    boost::array<char, 256> readBuffer;
    ip::tcp::socket socket;
};

class Server
{
public:
    Server(asio::io_service& ioService)
        :acceptor(ioService, ip::tcp::endpoint(ip::tcp::v4(), getPort()))
    {
        startAccept();
    }
private:
    void startAccept()
    {
        std::cout << "RServer::startAccept()" << std::endl;
        Connection::Pointer newConn =
            Connection::create(acceptor.io_service());

        acceptor.async_accept(newConn->getSocket(),
            boost::bind(&Server::handleAccept, this, newConn,
            asio::placeholders::error));
    }
    void handleAccept(Connection::Pointer newConn,
        const boost::system::error_code& error)
    {
        std::cout << "Server::handleAccept()" << std::endl;
        if(error)
        {
            std::cout << "CONNECTION ERROR: ";
            std::cout << boost::system::system_error(error).what();
            std::cout << std::endl;
        }
        else
        {
            std::cout << "Connection accepted" << std::endl;
            startAccept();
            newConn->startRead();
        }
    }
    ip::tcp::acceptor acceptor;
};

int main()
{
    std::cout << "Start server" << std::endl;
    asio::io_service ioService;
    RemoteAdminServer server(ioService);
    boost::system::error_code error;
    ioService.run(error);
}
È stato utile?

Soluzione

Devi modificare questo frammento di codice:

   void startRead()
   {
       std::cout << "Connection::startRead()" << std::endl;
       socket.async_read_some(boost::asio::buffer(readBuffer),
                              boost::bind(&Connection::handleRead,this,_1,_2));
   }

a:

void startRead()
{
     std::cout << "Connection::startRead()" << std::endl;
     socket.async_read_some(boost::asio::buffer(readBuffer),
                boost::bind(&Connection::handleRead,this->shared_from_this(),_1,_2));
}

Nota che ho passato un puntatore condiviso a bind . Ciò manterrà la tua istanza Connection fino a quando non verrà invocato il gestore. Altrimenti, il conteggio degli usi va a zero in Server :: startAccept e l'oggetto viene eliminato. Quindi, quando viene richiamato il gestore, la memoria non è valida e si verifica il temuto comportamento "indefinito". & Quot;

Altri suggerimenti

Penso che la tua corsa esista perché non hai più lavoro nella coda di lavoro.

Devi impedire che la corsa esca e distrugga il tuo oggetto di servizio.

Prova questo:

boost :: asio :: :: io_service lavoro

o semplicemente fai un

do { ioService.run( error ); } while( !error );
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top