升压asio async_write_some泄漏?
我一直在使用boost :: asio进行UDP和SocketCAN通信的应用程序。 今天,我注意到一些奇怪的东西 - 它正在泄漏内存!升压asio async_write_some泄漏?
所以我抓住我信赖的工具包,包括
echo 0 $(awk '/Private/ {print "+", $2}' /proc/`pidof main`/smaps) | bc
和Allinea DDT,并开始工作诊断这个问题。
我最终什么样的主意是下面的代码片段,它利用提高:: 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只是一个空函数坪看门狗。 我也试着
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
所以我挖了一个深一点,发现这个珍闻约boost.io_service:
io_service.run()完成,如果没有工作要做 - 所以通过运行它,然后发送更多的异步工作来完成,工作并没有完成。
这起源于有人翻转了ioservice.run()和异步读取回调分配以使代码看起来更好的问题 - 现在在运行之前没有堆积的工作,ioservice可以完成它的工作并返回。
解决它的荣誉。下一次,用附加信息编辑问题,这样人们会注意到(在发布此答案之前,我没有找到您的评论) – sehe
你的第一个怀疑应该永远是你自己的代码,而不是一个众所周知的,大量使用的库。你认为datSend()无关紧要,但这可能确实是泄漏发生的地方。请提供该功能的代码。 –
这是名副其实的空函数: 无效能:: datSend(){} 我用来登录此之际,但目前,它只是充当一个占位符。 –
您可以在主文件中设置一个调试钩子,并且一旦进入可疑功能,就可以在任何内存分配上设置一个断点。看看是否有任何人站出来 –