在串口通信中使用共享指针(`std::shared_ptr`)
在串口通信中使用共享指针(std::shared_ptr
)可以有效管理资源生命周期,避免内存泄漏和悬挂指针问题。以下是关键步骤和注意事项:
1. 管理串口对象生命周期
-
创建共享指针:使用
std::make_shared
初始化串口对象,确保资源自动管理。#include <boost/asio.hpp> #include <memory>auto port = std::make_shared<boost::asio::serial_port>(io_context); port->open("/dev/ttyUSB0");
-
绑定到异步操作:在异步读写中捕获
shared_ptr
,确保回调执行期间对象存活。port->async_read_some(boost::asio::buffer(data),[port, data](const boost::system::error_code& ec, size_t bytes) {if (!ec) {// 处理数据,port 对象保持有效}});
2. 管理缓冲区
- 动态缓冲区:使用
shared_ptr
包裹数据缓冲区,避免异步操作未完成时数据被释放。auto buffer = std::make_shared<std::vector<char>>(1024); port->async_write_some(boost::asio::buffer(*buffer),[buffer, port](const boost::system::error_code& ec, size_t bytes) {// 写入完成前,buffer 保持有效});
3. 避免循环引用
- 使用
weak_ptr
:若回调中需要访问父对象,使用std::weak_ptr
打破循环引用。class SerialHandler { public:void start_read() {auto self = weak_from_this(); // C++17 的 weak_from_thisport_->async_read_some(/* ... */,[self](/* ... */) {if (auto ptr = self.lock()) {ptr->handle_read(ec, bytes);}});} private:std::shared_ptr<boost::asio::serial_port> port_; };
4. 自定义删除器
- 释放资源:某些库需手动关闭串口,通过自定义删除器确保正确释放。
auto deleter = [](boost::asio::serial_port* port) {if (port->is_open()) port->close();delete port; }; std::shared_ptr<boost::asio::serial_port> port(new boost::asio::serial_port(io_context), deleter);
5. 线程安全与性能
- 原子性操作:
shared_ptr
的引用计数是线程安全的,但对象内部仍需同步。std::mutex mtx; port->async_read_some(/* ... */,[port, &mtx](/* ... */) {std::lock_guard<std::mutex> lock(mtx);// 安全访问共享资源});
- 性能权衡:高频通信中,
shared_ptr
的原子操作可能影响性能,可考虑对象池或静态分配。
6. 示例:完整异步读写
#include <boost/asio.hpp>
#include <memory>class SerialPort {
public:SerialPort(boost::asio::io_context& io, const std::string& device): port_(std::make_shared<boost::asio::serial_port>(io, device)) {}void start_async_read() {auto buffer = std::make_shared<std::vector<char>>(128);port_->async_read_some(boost::asio::buffer(*buffer),[this, buffer](const boost::system::error_code& ec, size_t bytes) {if (!ec) {process_data(*buffer, bytes);start_async_read(); // 持续读取}});}private:std::shared_ptr<boost::asio::serial_port> port_;void process_data(const std::vector<char>& data, size_t size) { /* ... */ }
};
注意事项
- 资源释放:确保所有异步操作完成后,
shared_ptr
的引用计数归零,避免内存泄漏。 - 超时处理:长时间未响应的操作需设置超时,防止对象因回调未触发而无法释放。
- 异常处理:在异步操作中捕获异常,确保
shared_ptr
能正常析构。
通过合理使用 shared_ptr
,可以简化串口通信中的资源管理,提升代码健壮性。