C++/Asio:使用 async_write 发送数据时崩溃

C++/Asio : crash when sending data using async_write

我正在使用 Asio 来处理我的网络 class。 苦恼了好久,一直想不通原因。

一、代码:

// .h
#pragma once

#include <asio.hpp>

class Connection : public std::enable_shared_from_this<Connection>
{
public:
    static std::shared_ptr<Connection> create(asio::io_context& IoContext);
    asio::ip::tcp::socket& getSocket();
    void start();

private:
    Connection(asio::io_context& IoContext);
    void startReading();
    void sendPacket(std::string Packet);
    void handle_read(const asio::error_code& error, size_t bytes);
    void handle_write(const asio::error_code& error, size_t bytes);
    void disconnect();

    asio::ip::tcp::socket socket;
    char packet[4096];
    bool started;
};

class Network
{
public:
    Network(asio::io_context& IoContext, unsigned short Port);
    void startServer();

private:
    void startAccept();
    void handle_accept(std::shared_ptr<Connection> connection, const asio::error_code& error);

    asio::io_context& ioContext;
    asio::ip::tcp::acceptor acceptor;
    bool started;
    std::vector<std::shared_ptr<Connection>> connections;
};
// .cpp

Connection::Connection(asio::io_context& IoContext)
    : socket(IoContext)
    , started(false)
    , packet("")
{

}

std::shared_ptr<Connection> Connection::create(asio::io_context& IoContext)
{
    return std::shared_ptr<Connection>(new Connection(IoContext));
}

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

void Connection::start()
{
    std::cout << "Connection::start();" << std::endl;
    if (!started)
    {
        startReading();
        started = true;
    }
}

void Connection::sendPacket(std::string Packet)
{
    socket.async_send(asio::buffer(Packet), [this](const asio::error_code& error, size_t bytes)
        { handle_write(error, bytes); });
}

void Connection::startReading()
{
    socket.async_receive(asio::buffer(packet), [this](const asio::error_code& error, size_t bytes)
        { handle_read(error, bytes); });
}

void Connection::handle_write(const asio::error_code& error, size_t bytes)
{
    std::cout << "WRITE : " << error.message() << " size : " << bytes << std::endl;
}

void Connection::handle_read(const asio::error_code& error, size_t bytes)
{
    if (error)
    {
        std::cout << "error:" << error.message();
        disconnect();
    }
    else
    {
        if (bytes > 0)
        {
            packet[bytes] = 0;
            std::string response = ...;
            sendPacket(response);
        }
    }
}


Network::Network(asio::io_context& IoContext, unsigned short Port)
    : ioContext(IoContext)
    , acceptor(ioContext, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), Port))
    , started(false)
{
    std::cout << "Server::Server();" << std::endl;
}

void Network::startServer()
{
    std::cout << "Server::startServer();" << std::endl;
    if (!started)
    {
        startAccept();
        started = true;
    }
}

void Network::startAccept()
{
    std::cout << "Server::startAccept();" << std::endl;
    std::shared_ptr<Connection> connection = Connection::create(ioContext);
    connections.push_back(connection);
    asio::error_code er;
    acceptor.async_accept(connection->getSocket(), std::bind(&Network::handle_accept, this, connection, er));
}

void Network::handle_accept(std::shared_ptr<Connection> connection, const asio::error_code& error)
{
    std::cout << "Server::handle_accept();" << std::endl;
    if (!error)
    {
        std::cout << "Ok" << std::endl;
        connection->start();
    }
    startAccept();
}

(我从cpp中删除了不必要的功能以使其更简洁,如果缺少某些功能请不要感到惊讶)

基本上,当我从 handle_read 函数中 sendPacket(something) 时它会崩溃。 我找到了两个修复程序:

if (bytes > 0)
{
    packet[bytes] = 0;
    std::string response = ...;
    sendPacket(my_member_string);
}
void Connection::sendPacket(std::string Packet)
{
    std::string *copy;
    socket.async_send(asio::buffer(copy), [this](const asio::error_code& error, size_t bytes)
        { handle_write(error, bytes); });
}

不删除它(如果我这样做,它会以同样的方式崩溃)。

那么,我的问题是:为什么 response 会导致崩溃?我读了很多关于“一生”的同一期,你能告诉我更多吗? response 的这段代码到底发生了什么? 另外,如果不是上述错误,修复此错误的干净方法是什么?

顺便说一句,我没有使用Boost。

提前致谢

不应该..._async 函数中的 lambda 中捕获 [this] 指针。因为 lambda 将超过 this 指针并且 this 将指向 lambda 调用中的无效地址。

在 lambda 中使用 [self=shared_from_this()] 并使用 self,因此该对象将通过异步调用使用共享指针。