Question

Pour quelque raison que ce soit, il en résulte une violation d'accès. Cependant, ne disposant d'aucune documentation / aide détaillée à ce sujet, je ne sais pas trop si je le fais mal. Depuis ce que j'ai vu sur le site boost, cela devrait être correct et afficher le contenu de chaque appel asio :: write du client sur une nouvelle ligne. Le client semble bien fonctionner. Bien que le serveur se soit arrêté au point où il n’a encore rien envoyé.

La violation d'accès se produit dans la ligne 275 dans basic_stream_socket.hpp. La cause semble être que l'objet (boost :: asio :: stream_socket_service) n'est pas initialisé (la valeur du pointeur this est 0xfeeefeee), mais je ne le fais pas. ne vois pas pourquoi ce n’est pas le cas.

La sortie du programme:

  

Démarrer le serveur
  Server :: startAccept ()
  Server :: handleAccept ()
  Connexion acceptée
  Connection :: startRead ()
  Server :: startAccept ()
  Connection :: handleRead ()
  READ ERROR: l'opération d'E / S a été annulée car un thread a quitté ou une demande d'application
  Connection :: startRead ()

Le code

#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);
}
Était-ce utile?

La solution

Vous devez modifier cet extrait de code:

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

à:

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));
}

Notez que j'ai passé un pointeur partagé à bind . Ceci gardera votre instance Connection jusqu'à ce que le gestionnaire soit appelé. Sinon, le nombre d'utilisations passe à zéro dans Server :: startAccept et l'objet est supprimé. Ensuite, lorsque le gestionnaire est appelé, la mémoire est invalide et vous rencontrez le redouté "comportement non défini".

Autres conseils

Je pense que votre parcours existe car il ne vous reste plus de travail dans la file d'attente.

Vous devez empêcher l'exécution de quitter et de détruire votre objet de service.

Essayez ceci:

scroll top