我有一个c ++ windows应用程序,工作正常。我使用Boost::asio
。当我尝试在Linux上移植时,应用程序根本无法正常工作。在被valgrind错误沮丧之后,我决定在Windows上运行DrMemory并修复首先出现的错误。我无法解决的一个错误是我已经扣除了关于我的套接字的错误。是否无法将scoped_ptr
与套接字一起使用?无论如何,这里是DrMemory记录的错误,后面是一些相关的代码。如果我将套接字的逻辑从智能指针更改为引用或裸指针,则代码不会编译。 (关于套接字的一些错误,我无法回想起它是什么,但它对于引用和指针是相同的)
我做错了什么?
DrMemory:http://pastebin.com/gHQYrCjA
NetworkEntity.cpp
#include "boost/asio.hpp"
#include "NetworkEntity.h"
#include "boost/bind.hpp"
NetworkEntity::NetworkEntity(std::string address, std::string port)
: address_(address),
port_(port)
{
}
void NetworkEntity::stop()
{
if (socket_)
{
socket_->close();
}
socket_.reset();
timeout_->cancel();
}
void NetworkEntity::check_timeout(const boost::system::error_code& error)
{
if (error != boost::asio::error::operation_aborted)
{
stop();
errorbuf_ << "timed out after " << TIMEOUT_ << " seconds\n";
}
}
std::vector<std::string> NetworkEntity::tcpPoll(const char* message, const char endOfMessage)
{
boost::asio::io_service io_service;
try{
//initialize timeout timer.
timeout_.reset(new boost::asio::deadline_timer(io_service));
timeout_->expires_from_now(boost::posix_time::seconds(TIMEOUT_));
timeout_->async_wait(boost::bind(&NetworkEntity::check_timeout, this, boost::asio::placeholders::error));
//initialize connection, which writes then reads.
tcp::resolver resolver(io_service);
start_connect(&io_service, resolver.resolve(tcp::resolver::query(address_, port_)), message, endOfMessage);
//run async operations, wait for their completion.
io_service.run();
//retrieve answer
std::vector<std::string> lines;
std::string line;
std::istream is(&answer_);
int i = 0;
while (std::getline(is, line)){
lines.push_back(line);
}
//reset answer to nothing (not needed but is a security)
answer_.consume(answer_.size());
request_.consume(request_.size());
setError(errorbuf_.str());
errorbuf_.str(""); // clear the contents
errorbuf_.clear();
return lines;
}
catch (std::exception& e){
errorbuf_ << "An exception has occured : " << e.what() << "\n";
return std::vector<std::string>{};
}
}
void NetworkEntity::start_connect(boost::asio::io_service* io_service, tcp::resolver::iterator endpoint_iterator, const std::string message, const char endOfMessage)
{
// Start the asynchronous connect operation.
socket_.reset(new tcp::socket(*io_service));
socket_->async_connect(endpoint_iterator->endpoint(),
boost::bind(&NetworkEntity::handle_connect, this, io_service, boost::asio::placeholders::error, message, endOfMessage));
}
void NetworkEntity::handle_connect(boost::asio::io_service* io_service, const boost::system::error_code& err, const std::string message, const char endOfMessage)
{
if (err)
{
stop();
errorbuf_ << "Connect error : " << err.message() << "\n";
}
else
{
start_write(message, endOfMessage);
}
}
void NetworkEntity::start_write(const std::string message, const char endOfMessage)
{
//convert message from string to streambuf
std::ostream request_stream(&request_);
request_stream << message;
//end of convertion
boost::asio::async_write(*socket_, request_,
boost::bind(&NetworkEntity::handle_write, this, boost::asio::placeholders::error, endOfMessage));
}
void NetworkEntity::handle_write(const boost::system::error_code& error, const char endOfMessage)
{
if (!error)
{
boost::asio::io_service io;
boost::asio::deadline_timer wait(io);
wait.expires_from_now(boost::posix_time::milliseconds(500));
wait.wait();
start_read(endOfMessage);
}
else
{
stop();
errorbuf_ << "Write error : " << error.message() << "\n";
}
}
void NetworkEntity::start_read(const char endOfMessage)
{
boost::asio::async_read_until(*socket_, answer_, endOfMessage,
boost::bind(&NetworkEntity::handle_read, this, boost::asio::placeholders::error));
}
void NetworkEntity::handle_read(const boost::system::error_code& error)
{
if (error)
{
errorbuf_ << "read error : " << error.message() << "\n";
}
stop();
}
NetworkEntity.h
#inclued "boost/asio.hpp"
#include "boost/array.hpp"
#include "boost/scoped_ptr.hpp"
#include "boost/shared_ptr.hpp"
#include "Error.h"
#ifndef NETWORK_ENTITY_H
#define NETWORK_ENTITY_H
using boost::asio::ip::tcp;
class NetworkEntity : private boost::noncopyable
{
public:
NetworkEntity(std::string address, std::string port);
std::vector<std::string> tcpPoll(const char* message, const char endOfMessage);
private:
void stop();
void check_timeout(const boost::system::error_code& error);
void start_write(const std::string message, const char endOfMessage);
void handle_write(const boost::system::error_code& error, const char endOfMessage);
void start_read(const char endOfMessage);
void start_connect(boost::asio::io_service* io_service, tcp::resolver::iterator endpoint_iterator, const std::string message, const char endOfMessage);
void handle_connect(boost::asio::io_service* io_service, const boost::system::error_code& error, const std::string message, const char endOfMessage);
void handle_read(const boost::system::error_code& error);
void timeoutHandler(const boost::system::error_code& error);
boost::scoped_ptr<tcp::socket> socket_;
boost::scoped_ptr<boost::asio::deadline_timer> timeout_;
std::string address_;
std::string port_;
boost::asio::streambuf answer_;
boost::asio::streambuf request_;
static const int TIMEOUT_ = 5;
std::stringstream errorbuf_; //loggable by functions I removed for the sake of simplicity
boost::shared_ptr<Error> error_;
boost::scoped_ptr<boost::asio::deadline_timer> logTimer_;
NetworkEntity(const NetworkEntity& e) = delete;
NetworkEntity & operator=(const NetworkEntity& e) = delete;
};
#endif
main.cpp(我没有尝试编译这个,对不起,如果有任何错误)
#include "NetworkEntity.h"
#include <iostream>
int main()
{
NetworkEntity n("192.168.0.36", "10001");
while (true){
std::string mes;
std::cin >> mes;
std::vector<std::string> ans = n.tcpPoll(mes.c_str(), '\n'); //message to send, last character expected to recieve (read until)
for (int i = 0; i < ans.size(); i++)
std::cout << ans[i] << "\n";
}
}
答案 0 :(得分:1)
希望能帮助您找到问题的一些提示:
boost::asio::io_service io_service
从NetworkEntity::tcpPoll
移至类成员变量。NetworkEntity::handle_write
中创建另一个ioservice,使用成员变量。NetworkEntity::tcpPoll
中,“timeout_.reset(new boost::asio::deadline_timer(io_service))
”会造成内存泄漏,请使用std::make_shared
NetworkEntity::handle_write
中的错误处理,并继续NetworkEntity::tcpPoll
中的io_service.run(),甚至没有出现错误。最后但并非最不重要的是,关于你的问题'是否不可能将scoped_ptr与套接字一起使用?',套接字是一回事,指针,作用域或不是另一回事。您应该阅读并了解智能指针,该术语背后没有任何魔法,只有引用计数,当该计数达到0时删除。
作为免费建议的奖励:忘记DrMemory并准确理解每一行,代码的每个陈述,如果函数有返回值,得到它并检查它......
祝你好运!答案 1 :(得分:0)
socket_.reset();
应位于先前的'if'区块内。
答案 2 :(得分:0)
最后,我让它在linux上运行并运行valgrind-clean。我的问题甚至不在这里显示的内容,而是我正在传递"10001\r"
而不是"10001"
作为端口,这使得解析器失败。 \r
getline
来自\n
(从文件中读取),仅删除了"10001\r\n"
中的{{1}}