boost:asio mem leak
-
hallo zusammen,
folgender code ist ein beispiel von alex ott, der code funktioniert soweit ganz gut jedoch gibt es ein memleak problem welches ich nicht nachvollziehen kann. leider reagiert der author nicht auf emails oder dergleichen.
bei jeder neuen connection wird, trotz destructen des connection objects, speicher nicht freigegeben. der leak kann ueber ein einfaches connection spamen per "while true; do bash -c "nc localhost 10001 &"; done" reproduziert werden.
über eventuelle hinweise/lösungen wäre ich sehr dankbar,
grüße,
sekhem/** * @file common.h * @author Alex Ott <alexott@gmail.com> * * @brief Declarations and includes, common for all boost::asio based programs * * */ #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> #include <boost/regex.hpp> #include <boost/bind.hpp> #include <boost/thread/thread.hpp> #include <iostream> #include <string> namespace ba=boost::asio; namespace bs=boost::system; typedef boost::shared_ptr<ba::ip::tcp::socket> socket_ptr; typedef boost::shared_ptr<ba::io_service> io_service_ptr; #include <deque> typedef std::deque<io_service_ptr> ios_deque; /** * Connection class, implementing async input/output * */ class connection : public boost::enable_shared_from_this<connection> { public: typedef boost::shared_ptr<connection> pointer; /** * Create new connection * * @param io_service io_service in which this connection will work * * @return pointer to newly allocated object */ static pointer create(ba::io_service& io_service) { return pointer(new connection(io_service)); } /** * Return socket, associated with this connection. This socket used in accept operation * * * @return reference to socket */ ba::ip::tcp::socket& socket() { return socket_; } /** * Start input/output chain with reading of headers from browser * */ void start() { // start reading of headers from browser boost::asio::async_read_until(socket_, buf, boost::regex("\r\n\r\n"), boost::bind(&connection::handle_read, shared_from_this(), ba::placeholders::error, ba::placeholders::bytes_transferred)); } private: /** * Initialize connection * * @param io_service * * @return */ connection(ba::io_service& io_service) : socket_(io_service) { } /** * Called when data written to browser * * @param error object, containing information about errors * @param bytes_transferred number of transferred bytes */ void handle_write(const boost::system::error_code& error, size_t bytes_transferred) { } /** * Called when data readed from browser * * @param error object, containing information about errors * @param bytes_transferred number of transferred bytes */ void handle_read(const boost::system::error_code& error, size_t bytes_transferred) { ba::async_write(socket_, ba::buffer(message_), boost::bind(&connection::handle_write, shared_from_this(), ba::placeholders::error, ba::placeholders::bytes_transferred)); } ba::ip::tcp::socket socket_; /**< socket, associated with browser */ boost::asio::streambuf buf; /**< buffer for request data */ static std::string message_; /**< data, that we'll return to browser */ }; std::string connection::message_="HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" "<html><head><title>test</title>" "</head><body><h1>Test</h1><p>This is a test!</p></body></html>"; /** * Server class * */ class server { public: /** * Initialize all needed data * * @param io_service reference to io_service * @param port port to listen on, by default - 10001 */ server(const ios_deque& io_services, int port=10001) : io_services_(io_services), acceptor_(*io_services.front(), ba::ip::tcp::endpoint(ba::ip::tcp::v4(), port)) { start_accept(); } private: /** * start connection accepting in async mode * */ void start_accept() { // select next io_service object io_services_.push_back(io_services_.front()); io_services_.pop_front(); // create new connection connection::pointer new_connection = connection::create(*io_services_.front()); // start acceptor in async mode acceptor_.async_accept(new_connection->socket(), boost::bind(&server::handle_accept, this, new_connection, ba::placeholders::error)); } /** * Run when new connection is accepted * * @param new_connection accepted connection * @param error reference to error object */ void handle_accept(connection::pointer new_connection, const boost::system::error_code& error) { if (!error) { new_connection->start(); start_accept(); } } ios_deque io_services_; /**< deque of pointers to io_services */ ba::ip::tcp::acceptor acceptor_; /**< object, that accepts new connections */ }; /** * Main routine * * @param argc number of arguments * @param argv pointers to arguments * * @return error code */ int main(int argc, char** argv) { try { int thread_num=10; // read number of threads with io_services from command line, if provided if(argc > 1) thread_num=boost::lexical_cast<int>(argv[1]); ios_deque io_services; std::deque<ba::io_service::work> io_service_work; boost::thread_group thr_grp; // create threads for each io_service for (int i = 0; i < thread_num; ++i) { io_service_ptr ios(new ba::io_service); io_services.push_back(ios); io_service_work.push_back(ba::io_service::work(*ios)); // run io_service in their own thread thr_grp.create_thread(boost::bind(&ba::io_service::run, ios)); } // create server server server(io_services); // wait until all thread will finished thr_grp.join_all(); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; }
-
Das passiert, wenn man lauter fremdes Zeug nimmt und es nicht versteht. Aber darum gibts ja so viele Foren, da findet man schon nen dummen der deine Arbeit macht.

-
tja schrieb:
Das passiert, wenn man lauter fremdes Zeug nimmt und es nicht versteht. Aber darum gibts ja so viele Foren, da findet man schon nen dummen der deine Arbeit macht.

das ist genau der punkt warum du hier den original code findest und nicht irgendeinen eigenen copy pasted kram. bevor ich es nicht verstehe, kann ich es auch nicht benutzen.
trotzdem danke,
sekhem
-
Schau dir lieber die examples von boost::asio selber an. Alleine den Deque<shared_ptr<io_service> > finde ich sehr komisch.
-
Schreibts lieber selber neu, da lernt man mehr.