我正在尝试使用Boost::asio
开发一个程序。这是我用来执行async_write()
:
template<typename T>
void Write(shared_ptr<std::vector<T>> data){
std::cout << "Write Method [std::vector]" << std::endl;
ioService.post(boost::bind(&TCPClient::DoWrite<T>, this, data));
}
然后,调用DoWrite()
方法实际发送向量中的数据:
template<typename T>
void DoWrite(shared_ptr<std::vector<T>> data){
std::cout << "DoWrite Method [std::vector]" << std::endl;
boost::asio::async_write( socket_,
boost::asio::buffer(*data),
boost::bind(&TCPClient::handle_write,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
std::cout << "async_write executed" << std::endl;
}
但是在运行时我遇到了这个错误:
程序:C:\ Windows \ SYSTEM32 \ MSVCP120D.dll文件:C:\ Program Files (x86)\ Microsoft Visual Studio 12.0 \ VC \ include \ vector Line:72
Expression:vector iterator not dereferencable
调查后我知道问题是传递给方法的std::vector<T>
不能保持足够活动,当写入发生时(因为它是异步的),向量不存在,所以我得到了这个错误。
我知道问题是因为如果我删除template
并且我的功能现在是这样的:
void DoWrite(std::vector<char> data){
std::cout << "DoWrite Method [std::vector]" << std::endl;
backupVector = data;
boost::asio::async_write( socket_,
boost::asio::buffer(backupVector),
boost::bind(&TCPClient::handle_write,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
std::cout << "async_write executed" << std::endl;
}
如果backupVector
是std::vector<char>
在类中,我没有收到错误,因为我有一个存在的引用,但我无法在运行时创建std::vector<T>
来存储传入在课堂上的向量(我是对的?我是C ++的新手)。
所以我读到了shared_ptr
:
std :: shared_ptr是一个保留共享所有权的智能指针 通过指针对象。几个shared_ptr对象可能拥有相同的内容 宾语。当任何一个对象被破坏并且其内存被释放时 发生以下情况:
拥有该对象的最后剩余的shared_ptr将被销毁。
拥有该对象的最后一个shared_ptr通过operator =或reset()分配另一个指针。
所以,如果我将指针传递给async_write
,为什么它被“销毁”,如果一个对象有引用它?还有其他办法吗?
这就是我使用Write()
方法的方法:
std::vector<char> data;
data.push_back('B');
data.push_back(bValue);
client.Write<char>(make_shared<std::vector<char>>(data));
Sleep(100000);
答案 0 :(得分:2)
我远远无法告诉你应该在这里做什么(缺少信息,只使用asio几次),但从this example猜测,你应该能够使用类似于:
的自定义缓冲区类来传递缓冲区// based on http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
template<class T>
class shared_const_buffer
{
public:
// Construct from a `shared_ptr`
explicit shared_const_buffer(std::shared_ptr<std::vector<T>> const& p_data)
: data_(p_data),
buffer_(boost::asio::buffer(*data_))
{}
// Implement the ConstBufferSequence requirements.
using value_type = boost::asio::const_buffer;
using const_iterator = boost::asio::const_buffer const*;
boost::asio::const_buffer const* begin() const { return &buffer_; }
boost::asio::const_buffer const* end() const { return &buffer_ + 1; }
private:
std::shared_ptr<std::vector<T>> data_;
boost::asio::const_buffer buffer_;
};
正如我对这个问题的评论中提到的,我不知道是否传递共享缓冲区以进行发送(写入)是一个好主意。
这是如何运作的:
在write函数中,传入一个缓冲区:
boost::asio::async_write( socket_,
boost::asio::buffer(backupVector), /*...*/ );
在此示例中,缓冲区是通过boost::asio::buffer
函数创建的。但是这个函数不会获取(并且不共享)参数的所有权,它只存储引用/指针。传递的缓冲区对象被复制到套接字(在作业队列中),直到作业完成为止。
通过使用shared_const_buffer
而不是boost::asio::buffer
创建的缓冲区对象,我们将向量的生命周期延长到创建的shared_const_buffer
对象的生命周期。因此,向量至少存在,直到工作完成。
请参阅the documentation of async_write
和the documentation of the buffer
function / buffer invalidation。
答案 1 :(得分:0)
只要执行Clint.write(...),对shared_ptr的引用就会存在。
如果你在这个参数之外声明它,它会活着更久,你的程序可能会工作。
你必须确保它保持足够长的时间,以便被boost :: asio称为函数异步写入。