I've been messing around with an application that uses boost::asio for both UDP and SocketCAN communication. Today, I noticed something weird - it was leaking memory!
So I grabbed my trusty toolkit consisting of
echo 0 $(awk '/Private/ {print "+", $2}' /proc/`pidof main`/smaps) | bc
and Allinea DDT and got to work diagnosing this issue.
What I ended up with was the following snippet, which utilizes boost::asio::posix::basic_stream_descriptor as it's base :
void Can::write(struct can_frame frame) {
stream_.async_write_some(boost::asio::buffer(&frame, sizeof(frame)),
boost::bind(&Can::datSend, this)
);
}
Here, the datSend is just an empty function that pings a watchdog. I've also tried
void Can::write(struct can_frame frame) {
stream_.write_some(boost::asio::buffer(&frame, sizeof(frame)));
}
But this gives an exception (invalid data) for some reason.
The rear end of this code looks something like this :
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");
}
}
Afterwards I just run the ioservice and that's that :
void Can::iosThreadWorker() { ioService_.run(); }
I've gone over quite a few stackoverflow topics as well as boost documentation, but can't seem to find why this function would leak memory.
Boost version - 1.60 G++ - 6.30 OS : Ubuntu 17.04