使用boost::asio::async_read时的segfault



我是用boost::asio进行串行端口通信的新手。

在我的程序中,代码可以正确地将数据写入串行端口。但在接收数据时,出现了分割错误。

我尝试用std::cout打印一个字符串来查找错误的部分,发现问题可能是由deadline_timer(sp_timeout(引起的。但我完全不知道该怎么处理…

这是我的代码:

std::vector<char> SP::asyncRead(size_t rcv_size)
{
sp_service->reset();
sp_is_read_timeout = false;
sp_available = false;
std::vector<char> sp_char(rcv_size);
try
{
boost::mutex::scoped_lock sl(*sp_mutex);
async_read( *sp_port, 
boost::asio::buffer(sp_char, rcv_size),
boost::bind(&SP::readCallback,
this,
boost::ref(*sp_timeout),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
std::cout << "now OK" << std::endl;
sp_timeout->expires_from_now(boost::posix_time::millisec(1500));
sp_timeout->async_wait(boost::bind( &SP::timeoutCallback, 
this,
boost::ref(*sp_port),
boost::asio::placeholders::error)
);
sp_service->run(); 
}
catch(const std::exception& e)
{
std::cerr << e.what() << 'n';
}
if (sp_available)
{
return sp_char;
}
else
{
throw "Serial port timeout";
}
}

更新:

下面提供的最小可复制示例:

main_node.cpp

#include "sp.h"
#include <iostream>
#include <thread>
#include <boost/thread/mutex.hpp>
std::shared_ptr<SP::SP> sp{ new SP::SP{"/dev/pts/6", 115200} };
int main(int argc, char **argv)
{
sp->open();
uint16_t _DATA = 0x0001;
while(true){
try
{
std::vector<char> rcv = sp->read_and_write(_DATA, 10);
for(auto i=0; i<rcv.size(); i++){
std::cout << std::hex << rcv[i] << std::endl;
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << 'n';
}
sleep(3);
}
sp->close();
return 0;
}

sp.cpp

#include "sp.h"
namespace SP
{
SP::SP(const std::string _serial_port, const int _baud_rate){
set_param_serial(_serial_port, _baud_rate);
}
SP::~SP(){
close();
}
void SP::set_param_serial(const std::string _serial_port, const int _baud_rate){
sp_serial_port = _serial_port;
sp_baud_rate = _baud_rate;
}
int SP::open(){
if(sp_port != NULL){
return -1;
}
if(sp_service){
sp_port.reset();
sp_service.reset();
}

sp_mutex = std::shared_ptr<boost::mutex>{new boost::mutex};
sp_service = std::shared_ptr<io_service>{new io_service()};
sp_port = std::shared_ptr<serial_port>{ new serial_port(*sp_service) };
try 
{
sp_port->open(sp_serial_port);
sp_port->set_option(serial_port_base::baud_rate(sp_baud_rate));
sp_port->set_option(serial_port_base::character_size(8));
sp_port->set_option(serial_port_base::parity(serial_port_base::parity::none));
sp_port->set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one));
}
catch (std::exception &ex){
std::cout << ex.what() << std::endl;
}
return 0;           
}
int SP::close(){
if(sp_port && sp_port->is_open()){
sp_port->close();
}
return 0;           
}
void SP::write(std::vector<char> _data){
if (sp_port->is_open()){
boost::mutex::scoped_lock lock(*sp_mutex);
auto size = sp_port->write_some(buffer(_data));
if(_data.size() != size){
throw "Write Size Error!!!";
}      
}
else
{
throw "Port not open";
}
}    
void SP::write_data(uint16_t _data)
{
std::vector<uint8_t> sp_data;
sp_data.clear();
sp_data.push_back(_data >> 8);
sp_data.push_back(_data);

std::vector<char> sp_char(sp_data.begin(), sp_data.end());
this->write(sp_char);
}
std::vector<char> SP::asyncRead(size_t rcv_size)
{
sp_service->reset();
sp_is_read_timeout = false;
sp_available = false;
std::vector<char> sp_char(rcv_size);
try
{
boost::mutex::scoped_lock sl(*sp_mutex);
async_read( *sp_port, 
boost::asio::buffer(sp_char, rcv_size),
boost::bind(&SP::readCallback,
this,
boost::ref(*sp_timeout),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
sp_timeout->expires_from_now(boost::posix_time::millisec(1500));
sp_timeout->async_wait(boost::bind(  &SP::timeoutCallback, 
this,
boost::ref(*sp_port),
boost::asio::placeholders::error
)
);
sp_service->run(); 

}
catch(const std::exception& ex)
{
std::cout << ex.what() << std::endl;
}
if (sp_available)
{
return sp_char;
}
else
{
throw "Serial port reading timeout";
}
}
void SP::readCallback(deadline_timer &timeout, const boost::system::error_code &error, std::size_t bytes_transferred)
{
if (error)
{
sp_available = false;
std::cerr << "readCallback Error " << error << std::endl;
return;
}
timeout.cancel();
sp_available = true;
}
void SP::timeoutCallback(serial_port &s_port, const boost::system::error_code &error)
{
if (error)
{
return;
}
sp_is_read_timeout = true;
sp_available = false;
s_port.cancel(); 
std::cerr << "Read timeout" << std::endl;
}
std::vector<char> SP::read_and_write(uint16_t _DATA, int num_bytes){
const std::lock_guard<std::mutex> lock(sp_std_mutex);
try
{
write_data(_DATA);
}
catch(const std::exception& e)
{
std::cerr << e.what() << 'n';
}
std::vector<char> response;
{
usleep(1500);
try
{
response = asyncRead(num_bytes);
}
catch(const std::exception& e)
{
std::cerr << e.what() << 'n';
}
}
return response;
}
}

sp.h

#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
using namespace boost::asio;
namespace SP
{
class SP
{
protected:
std::shared_ptr<io_service> sp_service;
std::shared_ptr<serial_port> sp_port;
std::shared_ptr<boost::mutex> sp_mutex;
std::shared_ptr<boost::mutex> sp_func_mutex;
std::string sp_serial_port;
int sp_baud_rate;

public:
SP(const std::string _serial_port, const int _baud_rate);
virtual ~SP();
public:
void set_param_serial(const std::string _serial_port, const int _baud_rate);
int open();
int close();
void write(std::vector<char> _data);
void write_data(uint16_t _data);
std::vector<char> asyncRead(size_t min_rcv);
void readCallback(deadline_timer &timeout, const boost::system::error_code &error, std::size_t bytes_transferred);
void timeoutCallback(serial_port &s_port, const boost::system::error_code &error);
std::vector<char> read_and_write(uint16_t _DATA, int num_bytes);
protected:
bool sp_is_read_timeout;
bool sp_available;
std::shared_ptr<deadline_timer> sp_timeout;
std::mutex sp_std_mutex;
};
}

我想我找到了问题所在…

在我的程序中,我使用deadline_timer来等待数据,但我只在sp.h文件中声明它。。。

发现这个问题后,我添加

sp_timeout = std::shared_ptr<deadline_timer>{new deadline_timer(*sp_service)};

并将其转换为SP::open()

这是个愚蠢的问题。很抱歉浪费了你的时间。。。

相关内容

  • 没有找到相关文章

最新更新