我一直在搞乱使用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版本 - 1.60 G ++ - 6.30 操作系统:Ubuntu 17.04
答案 0 :(得分:1)
所以我挖得更深一点,发现这个关于boost.io_service:
的小窍门io_service.run()完成,如果它没有工作要做 - 所以通过运行它然后发送更多的异步工作,工作没有完成。
这源于一个问题,有人翻了ioservice.run()和异步读取回调赋值使代码看起来更好 - 现在没有工作堆积在运行之前,ioservice可以完成它的工作并返回。