-1

I am trying to make a REASON API server that will accept requests from another application, but the problem is that after the first connection to it, it shuts down with the error -1073741819. When I went through it with the debugger, I found out that the error is called buffer_ "An unhandled exception was caused: a violation of read access.this was 0xffffffffffffffffff.", but I do not know how to solve this problem

cpp.file
-------------------
#include "Server.h"

using namespace boost::asio;
namespace beast = boost::beast;
namespace http = beast::http;
using tcp = boost::asio::ip::tcp;

Server::Server(boost::asio::io_service& io_service, int port)
    : acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
    socket_(io_service) {

    StartAccept();
}

void Server::StartAccept() {
    acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {
        if (!ec) {
            std::cout << "Client connected" << std::endl;
            ReadRequest();
        }
        else {
            std::cerr << "Client error: " << ec.message() << std::endl;
        }
    });
}

void Server::ReadRequest() {
    buffer_.consume(buffer_.size());
    buffer_.prepare(1024); 
    beast::http::async_read(socket_, buffer_, request_,
        [this](boost::system::error_code ec, size_t bytes_transferred) {
            if (!ec) {
                ProcessRequest();
            }
            else {
                std::cerr << "Error ReadRequest: " << ec.message() << std::endl;
            }
        });
}

void Server::ProcessRequest(){
    if (request_.method() == http::verb::get) {
        http::response<http::string_body> response(http::status::ok, request_.version());
        response.set(http::field::server, "Boost Beast Server");
        response.set(http::field::content_type, "text/plain");
        response.keep_alive(request_.keep_alive());
        response.body() = "Hello, World";
        response.prepare_payload();
        
        WriteResponse(response);
    }
    else {
        http::response<http::string_body> response(http::status::bad_request, request_.version());
        response.set(http::field::server, "Boost Beast Server");
        response.set(http::field::content_type, "text/plain");
        response.keep_alive(request_.keep_alive());
        response.body() = "Invalide request!";
        response.prepare_payload();
        
        WriteResponse(response);
    }
}

void Server::WriteResponse(boost::beast::http::response<boost::beast::http::string_body>& response_){
    http::async_write(socket_, response_,
        [this](boost::system::error_code ec, size_t byte) {
            if (ec) {
                std::cerr << "Error WriteResponse: " << ec.message() << std::endl;
            }
            StartAccept();
        });
}
h.file
---------------
#include <iostream>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <string>

class Server {
public:
    Server(boost::asio::io_service& io_service, int port);

private:
    void StartAccept(); 
    void ReadRequest(); 
    void ProcessRequest(); 
    void WriteResponse(boost::beast::http::response <boost::beast::http::string_body>& response_); 

    boost::asio::ip::tcp::acceptor acceptor_; 
    boost::asio::ip::tcp::socket socket_; 
    boost::beast::flat_buffer buffer_; 
    boost::beast::http::request<boost::beast::http::string_body> request_; 
};

3
  • The value -1073741819 is the same as 0xC0000005, which means you have an access violation (buffer overrun) in your program. Commented Dec 20, 2023 at 18:51
  • yes, but I don't understand how to fix it, it seems the code is correct, but why is there an overflow Commented Dec 20, 2023 at 19:04
  • 1
    @Someprogrammerdude SEGV or protection fault doesn't necessarily mean buffer overrun Commented Dec 20, 2023 at 19:43

1 Answer 1

0

The error originates in serializing the response.

You can tell by the assert happening in debug mode:

Client connected sotest:
intrusive/detail/hook_traits.hpp:63: static boost::intrusive::bhtraits_b ase<T, NodePtr, Tag, Type>::pointer boost::intrusive::bhtraits_base<T, NodePtr, Tag, Type>::to_value_ptr(node_ptr) [with T = boost::beast::http::basic_fields<std::allocator<char> >::element; NodePtr = boost::intrusive::list_node<v oid*>*; Tag = boost::intrusive::dft_tag; unsigned int Type = 1; pointer = boost::beast::http::basic_fields<std::all ocator<char> >::element*; node_ptr = boost::intrusive::list_node<void*>*]: Assertion '!!p' failed.

gdb tells us the place:

#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737345820608) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737345820608) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737345820608, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff793f476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff79257f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff792571b in __assert_fail_base (fmt=0x7ffff7ada130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x555555598094 "!!p", file=0x55555559cd90 "/home/sehe/cu...
#6  0x00007ffff7936e96 in __GI___assert_fail (assertion=0x555555598094 "!!p", file=0x55555559cd90 "/home/sehe/custom/superboost/boost/intrusive/detail/hook_traits.hpp", line=63...
#7  0x0000555555563c11 in boost::intrusive::bhtraits_base<boost::beast::http::basic_fields<std::allocator<char> >::element, boost::intrusive::list_node<void*>*, boost::intrusiv...
#8  boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator<char> >::element, boost::intrusive::list_node_traits<void*>, (boo...
#9  boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator<char> >::element, boost::intrusive::list_node_traits<void*>, (boo...
#10 boost::beast::http::basic_fields<std::allocator<char> >::writer::field_iterator::operator* (this=0x7fffffffd5c0) at /home/sehe/custom/superboost/boost/beast/http/impl/field...
#11 boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buffer, boost::beast::http::basic_fields<std::allocator<char> >::wri...
#12 0x0000555555590cba in boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buffer, boost::beast::http::basic_fields<std::...
#13 boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buf...
#14 boost::mp11::detail::mp_with_index_impl_<4ul>::call<0ul, boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_...
#15 boost::mp11::mp_with_index<4ul, boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::cons...
#16 boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buf...
#17 boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buffer, boost::asio::const_b...
#18 boost::asio::detail::buffer_size<boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::c...
#19 boost::asio::buffer_size<boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boost::beast::buffers_cat_view<boost::asio::const_buf...
#20 0x0000555555593cc3 in boost::beast::detail::buffer_bytes_impl::operator()<boost::beast::buffers_suffix<boost::beast::buffers_cat_view<boost::beast::detail::buffers_ref<boos...
#21 boost::beast::http::serializer<false, boost::beast::http::basic_string_body<char, std::char_traits<char>, std::allocator<char> >, boost::beast::http::basic_fields<std::allo...
#22 0x000055555556eec7 in boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail::write_msg_op<Server::WriteResponse(boost::b...
#23 0x000055555556f476 in boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail::write_msg_op<S...
#24 boost::asio::detail::binder0<boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail::write_m...
#25 boost::asio::detail::executor_function::complete<boost::asio::detail::binder0<boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::det...
#26 0x0000555555585b50 in boost::asio::detail::executor_function::operator() (this=<synthetic pointer>) at /home/sehe/custom/superboost/boost/asio/detail/executor_function.hpp:...
#27 boost::asio::io_context::basic_executor_type<std::allocator<void>, 4ul>::execute<boost::asio::detail::executor_function> (this=0x7fffffffdd70, f=...) at /home/sehe/custom/s...
#28 0x000055555556497a in boost::asio::execution::detail::any_executor_base::execute<boost::asio::detail::binder0<boost::asio::detail::binder2<boost::beast::http::detail::write...
#29 boost::asio::detail::work_dispatcher<boost::asio::detail::binder2<boost::beast::http::detail::write_some_op<boost::beast::http::detail::write_op<boost::beast::http::detail:...
#30 0x0000555555566511 in boost::asio::detail::executor_function::complete<boost::asio::detail::work_dispatcher<boost::asio::detail::binder2<boost::beast::http::detail::write_s...
#31 0x0000555555585a60 in boost::asio::detail::executor_function::operator() (this=<synthetic pointer>) at /home/sehe/custom/superboost/boost/asio/detail/executor_function.hpp:...
#32 boost::asio::detail::executor_op<boost::asio::detail::executor_function, std::allocator<void>, boost::asio::detail::scheduler_operation>::do_complete (owner=0x555555de6000,...
#33 0x00005555555678d7 in boost::asio::detail::scheduler_operation::complete (bytes_transferred=0, ec=..., owner=0x555555de6000, this=0x555555df4000) at /home/sehe/custom/super...
#34 boost::asio::detail::scheduler::do_run_one (ec=..., this_thread=..., lock=..., this=0x555555de6000) at /home/sehe/custom/superboost/boost/asio/detail/impl/scheduler.ipp:493...
#35 boost::asio::detail::scheduler::run (this=0x555555de6000, ec=...) at /home/sehe/custom/superboost/boost/asio/detail/impl/scheduler.ipp:210
#36 0x000055555555fe55 in boost::asio::io_context::run (this=0x7fffffffdf60) at /home/sehe/custom/superboost/boost/asio/impl/io_context.ipp:64
#37 main () at /home/sehe/Projects/stackoverflow/test.cpp:93

The reason is that the response is passed by reference to an async operation. Fix it e.g. by making it a member or using the type-erasing message_generator utility

Showing the latter:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <string>

class Server {
  public:
    Server(boost::asio::io_service& io_service, int port);

  private:
    using Request  = boost::beast::http::request<boost::beast::http::string_body>;
    using Response = boost::beast::http::message_generator;
    void     StartAccept();
    void     ReadRequest();
    Response ProcessRequest();
    void     WriteResponse(Response);

    boost::asio::ip::tcp::acceptor acceptor_;
    boost::asio::ip::tcp::socket   socket_;
    boost::beast::flat_buffer      buffer_;
    Request                        request_;
};

// #include "Server.h"

namespace beast = boost::beast;
namespace http  = beast::http;
using tcp       = boost::asio::ip::tcp;

Server::Server(boost::asio::io_service& io_service, int port)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
    , socket_(io_service) {
    StartAccept();
}

void Server::StartAccept() {
    acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {
        if (!ec) {
            std::cout << "Client connected" << std::endl;
            ReadRequest();
        } else {
            std::cerr << "Client error: " << ec.message() << std::endl;
        }
    });
}

void Server::ReadRequest() {
    buffer_.consume(buffer_.size());
    buffer_.prepare(1024);
    beast::http::async_read( //
        socket_, buffer_, request_, [this](boost::system::error_code ec, size_t /*bytes_transferred*/) {
            if (!ec) {
                WriteResponse(ProcessRequest());
            } else {
                std::cerr << "Error ReadRequest: " << ec.message() << std::endl;
            }
        });
}

Server::Response Server::ProcessRequest() {
    if (request_.method() == http::verb::get) {
        http::response<http::string_body> response(http::status::ok, request_.version());
        response.set(http::field::server, "Boost Beast Server");
        response.set(http::field::content_type, "text/plain");
        response.keep_alive(request_.keep_alive());
        response.body() = "Hello, World";
        response.prepare_payload();

        return response;
    } else {
        http::response<http::string_body> response(http::status::bad_request, request_.version());
        response.set(http::field::server, "Boost Beast Server");
        response.set(http::field::content_type, "text/plain");
        response.keep_alive(request_.keep_alive());
        response.body() = "Invalid request!";
        response.prepare_payload();

        return response;
    }
}

void Server::WriteResponse(Response res) {
    beast::async_write(socket_, std::move(res), [this](boost::system::error_code ec, size_t /*byte*/) {
        if (ec) {
            std::cerr << "Error WriteResponse: " << ec.message() << std::endl;
        }
        StartAccept();
    });
}

int main() {
    boost::asio::io_service ios;
    Server                  s(ios, 8989);

    ios.run();
}

The output of test:

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp 
./a.out&
sleep 1; curl "http://127.0.0.1:8989/test"

being

Hello, World

I suggest looking at the Beast async http server examples for more good practices!

UPDATE/BONUS

Also showing concurrent connections separating Server from Session and in the process reducing the includes in the header file:

Live On Coliru

  • File server.h

     // server.h
     #pragma once
     #include <boost/asio/any_io_executor.hpp>
     #include <boost/asio/ip/tcp.hpp>
    
     class Server {
       public:
         Server(boost::asio::any_io_executor ex, uint16_t port);
    
       private:
         void                           StartAccept();
         boost::asio::ip::tcp::acceptor acceptor_;
         struct Session;
     };
    
  • File server.cpp

     #include "server.h"
     #include <boost/asio.hpp>
     #include <boost/beast.hpp>
     #include <iostream>
     namespace beast  = boost::beast;
     namespace http   = beast::http;
     using tcp        = boost::asio::ip::tcp;
     using error_code = beast::error_code;
    
     struct Server::Session : std::enable_shared_from_this<Session> {
         Session(tcp::socket s) : socket_(std::move(s)) {}
         void Start() { ReadRequest(); }
    
       private:
         using Request  = http::request<http::string_body>;
         using Response = http::message_generator;
    
         void ReadRequest() {
             beast::http::async_read( //
                 socket_, buffer_, request_,
                 [this, self = shared_from_this()](error_code ec, size_t /*bytes_transferred*/) {
                     if (!ec) {
                         WriteResponse(ProcessRequest());
                     } else {
                         std::cerr << "Error ReadRequest: " << ec.message() << std::endl;
                     }
                 });
         }
    
         Response ProcessRequest() {
             if (request_.method() == http::verb::get) {
                 http::response<http::string_body> response(http::status::ok, request_.version());
                 response.set(http::field::server, "Boost Beast Server");
                 response.set(http::field::content_type, "text/plain");
                 response.keep_alive(request_.keep_alive());
                 response.body() = "Hello, World";
                 response.prepare_payload();
    
                 return response;
             } else {
                 http::response<http::string_body> response(http::status::bad_request, request_.version());
                 response.set(http::field::server, "Boost Beast Server");
                 response.set(http::field::content_type, "text/plain");
                 response.keep_alive(request_.keep_alive());
                 response.body() = "Invalid request!";
                 response.prepare_payload();
    
                 return response;
             }
         }
    
         void WriteResponse(Response res) {
             beast::async_write(socket_, std::move(res),
                                [self = shared_from_this()](error_code ec, size_t /*byte*/) {
                                    if (ec) {
                                        std::cerr << "Error WriteResponse: " << ec.message() << std::endl;
                                    }
                                });
         }
         tcp::socket        socket_;
         beast::flat_buffer buffer_;
         Request            request_;
     };
    
     Server::Server(boost::asio::any_io_executor ex, uint16_t port)
         : acceptor_(ex, tcp::endpoint(tcp::v4(), port)) {
         StartAccept();
     }
    
     void Server::StartAccept() {
         acceptor_.async_accept([this](error_code ec, tcp::socket s) {
             if (!ec) {
                 std::cout << "Client accepted: " << s.remote_endpoint() << std::endl;
                 std::make_shared<Session>(std::move(s))->Start();
             } else {
                 std::cerr << "Accept error: " << ec.message() << std::endl;
             }
             StartAccept();
         });
     }
    
     int main() {
         boost::asio::io_context ioc;
         Server                  s(ioc.get_executor(), 7878);
    
         ioc.run();
     }
    
Sign up to request clarification or add additional context in comments.

2 Comments

Added fixed example.
PS: the consume/prepare look odd/wrong. It "makes sense" because you're reusing the buffer after accepting new connections, but still the prepare is redundant and you could just use buffer_.clear() instead. Of course, you want separation of concurrent sessions anyways: coliru.stacked-crooked.com/a/98753ac210e657cb. Note also that the header file now contains far fewer dependencies (no beast in the header at all)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.