2017-09-26 152 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