gpt4 book ai didi

c++ - Asio tcp 套接字上的未初始化读取错误

转载 作者:行者123 更新时间:2023-11-28 06:47:50 25 4
gpt4 key购买 nike

我有一个运行良好的 C++ Windows 应用程序。我使用 Boost::asio。当我尝试在 Linux 上移植时,该应用程序根本无法按预期运行。在对 valgrind 错误感到灰心之后,我决定在 Windows 上运行 DrMemory 并修复首先出现的错误。我无法修复的一个错误是我推断出与我的套接字有关的错误。不能将 scoped_ptr 与套接字一起使用吗?无论如何,这里是 DrMemory 记录的错误,后面是一些相关代码。如果我将套接字的逻辑从智能指针更改为引用或裸指针,则代码不会编译。 (关于套接字的一些错误,我不记得到底是什么,但对于引用和指针来说是一样的)

我做错了什么?

博士内存:http://pastebin.com/gHQYrCjA

网络实体.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";
}
}

最佳答案

一些提示可以帮助您找到问题,希望:

  1. boost::asio::io_service io_serviceNetworkEntity::tcpPoll 移动到类成员变量。
  2. 我不明白为什么要在 NetworkEntity::handle_write 中创建另一个 ioservice,请使用成员变量。
  3. NetworkEntity::tcpPoll 中,'timeout_.reset(new boost::asio::deadline_timer(io_service))' 会造成内存泄漏,使用 std::make_shared
  4. 我不理解 NetworkEntity::handle_write 中的错误处理,因为您“重置”套接字,并继续 NetworkEntity::tcpPoll 中的 io_service.run()甚至没有发现任何错误。

最后但同样重要的是,关于您的问题“是否可以将 scoped_ptr 与套接字一起使用?”,套接字是一回事,指针、作用域或非作用域是另一回事。您应该阅读和了解智能指针,该术语背后没有什么神奇之处,只有一个引用计数,并在该计数达到 0 时删除。

还有一个额外的免费建议:忘记 DrMemory 并准确理解代码的每一行、每条语句,如果函数有返回值,获取并检查它...

祝你好运!

关于c++ - Asio tcp 套接字上的未初始化读取错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24633637/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com