Boost asio async_write_some 泄漏?
Boost asio async_write_some leaking?
我一直在搞一个使用 boost::asio 进行 UDP 和 SocketCAN 通信的应用程序。
今天,我发现了一些奇怪的事情——内存泄漏!
所以我抓住了我值得信赖的工具包,其中包括
echo 0 $(awk '/Private/ {print "+", }' /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(); }
我浏览了很多 Whosebug 主题以及 boost 文档,但似乎无法找到此函数会泄漏内存的原因。
增强版 - 1.60
G++ - 6.30
OS : Ubuntu 17.04
所以我深入挖掘并发现了关于 boost.io_service 的花絮:
io_service.run() 如果没有工作可完成 - 所以通过 运行 它然后发送更多要完成的异步工作,工作没有完成。
这源于一个问题,即有人翻转了 ioservice.run() 和异步读取回调分配以使代码看起来更好 - 现在在 运行 和 ioservice 之前没有工作堆积只需完成它的工作 return.
我一直在搞一个使用 boost::asio 进行 UDP 和 SocketCAN 通信的应用程序。 今天,我发现了一些奇怪的事情——内存泄漏!
所以我抓住了我值得信赖的工具包,其中包括
echo 0 $(awk '/Private/ {print "+", }' /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(); }
我浏览了很多 Whosebug 主题以及 boost 文档,但似乎无法找到此函数会泄漏内存的原因。
增强版 - 1.60 G++ - 6.30 OS : Ubuntu 17.04
所以我深入挖掘并发现了关于 boost.io_service 的花絮:
io_service.run() 如果没有工作可完成 - 所以通过 运行 它然后发送更多要完成的异步工作,工作没有完成。
这源于一个问题,即有人翻转了 ioservice.run() 和异步读取回调分配以使代码看起来更好 - 现在在 运行 和 ioservice 之前没有工作堆积只需完成它的工作 return.