我一直在搞乱一个使用 boost::asio 进行 UDP 和 SocketCAN 通信的应用程序。今天,我注意到一些奇怪的事情——它正在泄漏内存!
所以我抓住了我值得信赖的工具包,其中包括
echo 0 $(awk '/Private/ {print "+", $2}' /proc/`pidof main`/smaps) | bc
和 Allinea DDT 并开始诊断这个问题。
我最终得到的是以下片段,它利用 boost::asio::posix::basic_stream_descriptor 作为它的基础:
void Can::write(struct can_frame frame) {
stream_.async_write_some(boost::asio::buffer(&frame, sizeof(frame)),
boost::bind(&Can::datSend, this)
);
}
在这里,datSend 只是一个 ping 看门狗的空函数。我也试过
void Can::write(struct can_frame frame) {
stream_.write_some(boost::asio::buffer(&frame, sizeof(frame)));
}
但这出于某种原因给出了异常(无效数据)。
这段代码的后端看起来像这样:
boost::asio::io_service ioService_;
boost::asio::posix::basic_stream_descriptor<> stream_;
Constructor() : stream_(ioService_) {
socketDescriptor_ = socket(PF_CAN, SOCK_RAW, CAN_RAW);
struct timeval timeout {
.tv_sec = 5,
.tv_usec = 0
};
if (setsockopt(socketDescriptor_, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<char *>(&timeout),
sizeof(timeout)) < 0) {
throw std::string("Error setting CAN socket timeout");
}
strcpy(interfaceRequest_.ifr_name, interfaceName.c_str());
ioctl(socketDescriptor_, SIOCGIFINDEX, &interfaceRequest_);
socketAddress_.can_family = AF_CAN;
socketAddress_.can_ifindex = interfaceRequest_.ifr_ifindex;
stream_.assign(socketDescriptor_);
if (bind(socketDescriptor_, (struct sockaddr *)&socketAddress_,
sizeof(socketAddress_)) < 0) {
throw std::string("Error in socket bind");
}
}
之后我只运行 ioservice 就是这样:
void Can::iosThreadWorker() { ioService_.run(); }
我已经阅读了很多 stackoverflow 主题以及 boost 文档,但似乎无法找到为什么这个函数会泄漏内存。
Boost 版本 - 1.60 G++ - 6.30 操作系统:Ubuntu 17.04