2009-08-03 6 views
7

Pour une raison quelconque, cela entraîne une violation d'accès, mais n'ayant aucune documentation/aide détaillée à ce sujet, je ne suis pas sûr de savoir où je me trompe. Étant donné ce que j'ai vu sur le site boost, cela devrait être correct, et imprimer le contenu de chaque appel asio :: write du client vers une nouvelle ligne. Le client semble bien fonctionner. Bien que le serveur tombe en panne, mais il n'a encore rien envoyé. La violation d'accès se produit dans basic_stream_socket.hpp sur la ligne 275. La cause semble être que l'objet (boost :: asio :: stream_socket_service) n'est pas initialisé (la valeur de ce pointeur est 0xfeeefeee), mais je ne le fais pas. Je ne vois pas pourquoi ça ne l'est pas.boost :: asio, erreur de lecture asynchrone

Les programmes de sortie:

Start server
Server::startAccept()
Server::handleAccept()
Connection accepted
Connection::startRead()
Server::startAccept()
Connection::handleRead()
READ ERROR: The I/O operation has been aborted because either a thread exited or an application request
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); 
} 

Répondre

11

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 transmis un pointeur partagé à bind. Cela maintiendra votre instance Connection jusqu'à ce que le gestionnaire soit appelé. Sinon, le nombre d'utilisations passe à Server::startAccept et l'objet est supprimé. Ensuite, lorsque le gestionnaire est appelé, la mémoire est invalide et vous rencontrez le redouté "comportement indéfini".

0

Je pense que votre course existe parce que vous n'avez pas laissé le travail dans la file d'attente de travail.

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

Ou essayez ceci:

boost::asio::io_service::work

ou tout simplement faire un

do { ioService.run(error); } while(!error); 
+0

Il ne quitte jamais run() de toute façon –

+0

Vous ne pouvez pas réexécuter 'io_service' sans le réinitialiser. –

Questions connexes