2017-09-26 131 views
0

我一直在使用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

+0

你的第一个怀疑应该永远是你自己的代码,而不是一个众所周知的,大量使用的库。你认为datSend()无关紧要,但这可能确实是泄漏发生的地方。请提供该功能的代码。 –

+0

这是名副其实的空函数: 无效能:: datSend(){} 我用来登录此之际,但目前,它只是充当一个占位符。 –

+0

您可以在主文件中设置一个调试钩子,并且一旦进入可疑功能,就可以在任何内存分配上设置一个断点。看看是否有任何人站出来 –

回答

1

所以我挖了一个深一点,发现这个珍闻约boost.io_service:

io_service.run()完成,如果没有工作要做 - 所以通过运行它,然后发送更多的异步工作来完成,工作并没有完成。

这起源于有人翻转了ioservice.run()和异步读取回调分配以使代码看起来更好的问题 - 现在在运行之前没有堆积的工作,ioservice可以完成它的工作并返回。

+1

解决它的荣誉。下一次,用附加信息编辑问题,这样人们会注意到(在发布此答案之前,我没有找到您的评论) – sehe