부스트 :: ASIO, 비동기 판독 오류
-
10-07-2019 - |
문제
어떤 이유로 든 이로 인해 액세스 위반이 발생하지만 이에 대한 자세한 문서/도움말이 없습니다. 내가 어디에서 잘못하고 있는지 잘 모르겠습니다. 부스트 사이트에서 본 것에 따라 이것은 정확해야하며, 각 ASIO :: 클라이언트에서 새 라인으로의 통화를 작성합니다. 클라이언트는 잘 작동하는 것 같습니다. 시점에서 서버는 충돌하지만 아직 아무것도 보내지 않았습니다.
액세스 위반은 275 행의 Basic_stream_Socket.hpp에서 발생합니다. 원인은 객체 (boost :: asio :: stream_socket_service)가 초기화되지 않은 것 같습니다 (이 포인터의 값은 0xfeeefeee입니다). 그렇지 않습니다.
프로그램 출력 :
서버를 시작하십시오
서버 :: startAccept ()
서버 :: HandleAccept ()
연결이 허용됩니다
연결 :: Startread ()
서버 :: startAccept ()
연결 :: handleread ()
오류 읽기 : 스레드가 종료되거나 응용 프로그램 요청이므로 I/O 작업이 중단되었습니다.
연결 :: Startread ()
코드
#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);
}
해결책
이 코드 스 니펫을 변경해야합니다.
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));
}
내가 통과했음을 주목했다 공유 포인터 에게 bind
. 이것은 당신을 유지할 것입니다 Connection
핸들러가 호출 될 때까지 주변 인스턴스. 그렇지 않으면 사용 카운트가 0으로 이동합니다 Server::startAccept
그리고 객체가 삭제됩니다. 그런 다음 핸들러가 호출되면 메모리가 유효하지 않으며 끔찍한 "정의되지 않은 행동"을 경험합니다.
다른 팁
작업 대기열에 작업이 남아 있지 않기 때문에 실행이 존재한다고 생각합니다.
실행이 서비스 객체를 종료하고 파괴하는 것을 방지해야합니다.
이것을 시도하십시오 :
부스트 :: asio :: io_service :: Work
아니면 그냥하십시오
do { ioService.run( error ); } while( !error );