提高截止时间_计时器导致堆栈缓冲区溢出 [英] Boost deadline_timer causes stack-buffer-overflow

查看:59
本文介绍了提高截止时间_计时器导致堆栈缓冲区溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的几天里,我一直被Boost Deadline_timer困在一个非常奇怪的错误中.桌面版:Ubuntu 18.04升压:v1.65.01

当我在我的类的构造函数中创建新的duration_timer时,AddressSanitizer会捕获来自Boost库内部的堆栈缓冲区溢出.

我有一些发现:

  • 我还注意到,没有AddressSanitizer会出问题,因为expiry_time为负,或者由于超时而一直没有超时,所以计时器一直都在超时.因此,似乎某人正在某个地方更改该内存区域.
  • 我正在使用的类很大,并且正在使用相同的Boost io_service通过UDP发送数据.
  • 我无法仅在独立的源文件中重现该错误.
  • 当我删除代码以找出问题所在时,无论我删除多少代码,问题仍然存在.我只剩下一个主文件,创建一个io_service和duration_timer,它仍然抛出该错误.如果我将其复制到另一个文件中并复制CMakeLists条目,我仍然无法复制它.

该类的结构不是很复杂,这是一个示例类,它实际上具有相同的功能udp_timer.hpp

  #include"boost/asio.hpp"UdpTimer类{上市:UdpTimer();〜UdpTimer();无效的run();void timer_callback(const boost :: system :: error_code& e);void udp_callback(const boost :: system :: error_code& e,size_t bytes_recvd);boost :: asio :: io_service io;私人的:boost :: asio :: ip :: udp :: socket * socket;boost :: asio :: ip :: udp :: endpoint * ep;boost :: asio :: deadline_timer * timer;char recv_buf [2048];unsigned int tot_bytes_recved;}; 

udp_timer.cpp

  #include"udp_timer.hpp"#include"boost/bind.hpp"#include< iostream>UdpTimer :: UdpTimer(){//设置UDP部分ep =新的boost :: asio :: ip :: udp :: endpoint(boost :: asio :: ip :: udp :: v4(),30042);套接字=新的boost :: asio :: ip :: udp :: socket(io,* ep);套接字-> async_receive_from(boost :: asio :: buffer(recv_buf,2048),* ep,boost :: bind(& UdpTimer :: udp_callback,这个,boost :: asio :: placeholders :: error,boost :: asio :: placeholders :: bytes_transferred));tot_bytes_recved = 0;计时器=新的boost :: asio :: deadline_timer(io,boost :: posix_time :: seconds(1));timer-> async_wait(boost :: bind(& UdpTimer :: timer_callback,this,boost :: asio :: placeholders :: error));}UdpTimer ::〜UdpTimer(){删除ep;删除套接字;删除计时器;}无效的UdpTimer :: run(){io.run();//永不返回}//计时器回调.打印信息和重置计时器无效的UdpTimer :: timer_callback(const boost :: system :: error_code& e){如果(e)返回;静态整数计数= 0;std :: cout<"计时器回调#"<< count ++<<"收到的字节数="<< tot_bytes_recved<< std :: endl;std :: cout<< recv_buf<< std :: endl;timer-> expires_from_now(boost :: posix_time :: seconds(1));timer-> async_wait(boost :: bind(& UdpTimer :: timer_callback,this,boost :: asio :: placeholders :: error));}//Udp回调.更新接收字节数void UdpTimer :: udp_callback(const boost :: system :: error_code& e,size_t bytes_recvd){如果(e)返回;tot_bytes_recved + = bytes_recvd;套接字-> async_receive_from(boost :: asio :: buffer(recv_buf,2048),* ep,boost :: bind(& UdpTimer :: udp_callback,这个,boost :: asio :: placeholders :: error,boost :: asio :: placeholders :: bytes_transferred));}int main(void){UdpTimer udp_timer;udp_timer.run();} 

放置在程序中足以产生该错误.

  ===================================================================== 20441 ==错误:AddressSanitizer:pc 0x55d73239950c bp上地址0x7ffe4a7621d0的堆栈缓冲区溢出0x7ffe4a761f50 sp 0x7ffe4a761f40在0x7ffe4a7621d0线程T0上写入大小16#0 0x55d73239950b在boost :: date_time :: base_time< boost :: posix_time :: ptime,boost :: date_time :: split_timedate_system< boost :: posix_time :: posix_time_system_config>> :: base_time(boost :: gregorian :: date const& ;, boost :: posix_time :: time_duration const& ;, boost :: date_time :: dst_flags)(/home/erl/dev/test/build/prog_ins + 0x61950b)#1 0x55d732396495在boost :: posix_time :: ptime :: ptime(boost :: gregorian :: date,boost :: posix_time :: time_duration)/usr/include/boost/date_time/posix_time/ptime.hpp:40#2 0x55d7323d4855在boost :: date_time :: microsec_clock< boost :: posix_time :: ptime> :: create_time(tm *(*)(long const *,tm *))/usr/include/boost/date_time/microsec_time_clock.hpp:116#3 0x55d7323d12f6在boost :: date_time :: microsec_clock< boost :: posix_time :: ptime> :: universal_time()/usr/include/boost/date_time/microsec_time_clock.hpp:76#4 0x55d7323cb501在boost :: asio :: time_traits< boost :: posix_time :: ptime> :: now()/usr/include/boost/asio/time_traits.hpp:48#5 0x55d7323db197在boost :: asio :: detail :: deadline_timer_service< boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: expires_from_now(boost :: asio :: detail :: deadline_timer_service< boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: implementation_type& ;, boost :: posix_time :: time_duration constboost :: system :: error_code&)(/home/erl/dev/test/build/prog_ins + 0x65b197)#6 0x55d7323d6a25在boost :: asio :: deadline_timer_service< boost :: posix_time :: ptime,boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: expires_from_now(boost :: asio :: detail :: deadline_timer_service< boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: implementation_type& ;, boost :: posix_time :: time_duration constboost :: system :: error_code&)/usr/include/boost/asio/deadline_timer_service.hpp:129#7 0x55d7323d2ca8在boost :: asio :: basic_deadline_timer< boost :: posix_time :: ptime,boost :: asio :: time_traits< boost :: posix_time :: ptime> ;, boost :: asio :: deadline_timer_service< boost::ptime,boost :: asio :: time_traits< boost :: posix_time :: ptime>>> :: basic_deadline_timer(boost :: asio :: io_service& ;, boost :: posix_time :: time_duration const&)/usr/include/boost/asio/basic_deadline_timer.hpp:187#8 0x55d7323b7f22在InsHandler :: InsHandler(InsConfig *,spdlog :: logger *)/home/erl/dev/test/src/InsHandler.cpp:57中#9 0x55d7323a3fb0在主/home/erl/dev/test/src/prog_ins.cpp:74中__libc_start_main中的#10 0x7f369ed89bf6(/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)_start中的#11 0x55d7322894d9(/home/erl/dev/test/build/prog_ins + 0x5094d9)地址0x7ffe4a7621d0位于线程T0的堆栈中,位于帧中的偏移量480处#0 0x55d7323d426f在boost :: date_time :: microsec_clock< boost :: posix_time :: ptime> :: create_time(tm *(*)(long const *,tm *))/usr/include/boost/date_time/microsec_time_clock.hpp:80该框架有10个对象:[32,34)'< unknown>'[96,98)'<未知>'[160,162)'<未知>'[224,228)'d'[288,296)'t'[352,360)'td'[416,424)'<未知>'[480,488)'<未知>'< ==偏移量480处的内存访问部分使此变量溢出[544,560)电视"[608,664)'curr'提示:如果您的程序使用某些自定义堆栈展开机制或swapcontext,则可能是误报(*支持* longjmp和C ++异常)摘要:AddressSanitizer:在boost :: date_time :: base_time< boost :: posix_time :: ptime,boost :: date_time :: split_timedate_system<中,堆栈缓冲区溢出(/home/erl/dev/test/build/prog_ins + 0x61950b)boost :: posix_time :: posix_time_system_config>> :: base_time(boost :: gregorian :: date const& ;, boost :: posix_time :: time_duration const& ;, boost :: date_time :: dst_flags)越野车地址周围的影子字节:0x1000494e43e0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000494e43f0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f10x1000494e4400:f1 f1 f8 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2 f2 f20x1000494e4410:f2 f2 f8 f2 f2 f2 f2 f2 f2 f2 04 f2 f2 f2 f2 f20x1000494e4420:f2 f2 00 f2 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 f2=> 0x1000494e4430:f2 f2 00 f2 f2 f2 f2 f2 f2 f2 [00] f2 f2 f2 f2 f20x1000494e4440:f2 f2 00 00 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 000x1000494e4450:00 f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x1000494e4460:00 00 00 00 f1 f1 f1 f1 00 f2 f2 f2 f2 f2 f2 f20x1000494e4470:00 f2 f2 f2 00 00 00 00 00 00 00 00 00 00 00 000x1000494e4480:00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f2 f2影子字节图例(一个影子字节代表8个应用程序字节):可寻址:00部分可寻址:01 02 03 04 05 06 07堆左红区:fa释放堆区域:fd堆栈左红区:f1堆栈中区:f2堆栈右红区:f3退货后堆叠:f5范围后使用堆栈:f8全球Redzone:f9全局初始化顺序:f6用户中毒:f7容器溢出:FC数组cookie:ac物件内Redzone:bbASan内部:fe左alloca redzone:ca正确的alloca redzone:cb== 20441 ==正在终止 

从此错误打印输出看来,Boost库中似乎有一个错误,该错误将16字节写入仅分配给8字节的内容.但是,为什么表面应该如此断断续续呢?我还注意到,我们有几个词被标记为"f8",即"scope-after-scope".这是否意味着我们程序的另一部分在超出范围后正在使用指向已分配堆栈的对象的指针?

与valgrind一起运行给了我

  == 27251 ==条件跳转或移动取决于未初始化的值== 27251 == at 0x578FA1:boost :: date_time :: int_adapter< long> :: is_infinity()const(int_adapter.hpp:114)== 27251 ==通过0x5772A9:boost :: date_time :: int_adapter< long> :: is_special()const(int_adapter.hpp:131)== 27251 ==通过0x5A1069:boost :: date_time :: counted_time_rep< boost :: posix_time :: millisec_posix_time_system_config> :: is_special()const(time_system_counted.hpp:108)== 27251 ==通过0x59FCD3:boost :: date_time :: counted_time_system< boost :: date_time :: counted_time_rep< boost :: posix_time :: millisec_posix_time_system_config>> :: add_time_duration(boost :: date_time :: counted_time_rep< boost :: posix_time :: millisec_posix_time_system_config> const& ;, boost :: posix_time :: time_duration(time_system_counted.hpp:226)== 27251 ==通过0x59EA90:boost :: date_time :: base_time< boost :: posix_time :: ptime,boost :: date_time :: counted_time_system< boost :: date_time :: counted_time_rep< boost :: posix_time :: millisec_posix_gt_time_system>> :: operator +(boost :: posix_time :: time_duration const&)const(time.hpp:163)== 27251 ==通过0x59E46B:boost :: asio :: time_traits< boost :: posix_time :: ptime> :: add(boost :: posix_time :: ptime const& ;, boost :: posix_time :: time_duration const&)(time_traits.hpp:57)== 27251 ==通过0x5A1BEC:boost :: asio :: detail :: deadline_timer_service< boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: expires_from_now(boost :: asio :: detail :: deadline_timer_service< boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: implementation_type& ;, boost :: posix_time :: time_duration constboost :: system :: error_code&)(deadline_timer_service.hpp:161)== 27251 ==通过0x5A0811:boost :: asio :: deadline_timer_service< boost :: posix_time :: ptime,boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: expires_from_now(boost :: asio :: detail :: deadline_timer_service< boost :: asio :: time_traits< boost :: posix_time :: ptime>> :: implementation_type& ;, boost :: posix_time :: time_duration constboost :: system :: error_code&)(deadline_timer_service.hpp:129)== 27251 ==通过0x59F20B:boost :: asio :: basic_deadline_timer< boost :: posix_time :: ptime,boost :: asio :: time_traits< boost :: posix_time :: ptime> ;, boost :: asio :: deadline_timer_service< boost:: posix_time :: ptime,boost :: asio :: time_traits< boost :: posix_time :: ptime>>> :: basic_deadline_timer(boost :: asio :: io_service& ;, boost :: posix_time :: time_duration const&)(basic_deadline_timer.hpp:187)== 27251 ==通过0x59DA57:OutputTimer :: OutputTimer(boost :: asio :: io_service *,unsigned int,boost :: function< OutputStates()>)(output_timer.cpp:5)== 27251 ==通过0x5877D5:InsHandler :: InsHandler(InsConfig *,spdlog :: logger *)(InsHandler.cpp:57)== 27251 ==通过0x57B149:主(senti_ins.cpp:74)== 27251 ==未初始化的值是由堆栈分配创建的== 27251 ==在0x59FB3C:boost :: date_time :: microsec_clock< boost :: posix_time :: ptime> :: create_time(tm *(*)(long const *,tm *))(microsec_time_clock.hpp:80) 

我真的在这里迷路了.我对源代码所做的更改与所产生的行为之间确实没有任何联系.我可以通过删除完全不相关的头文件来删除该错误.但是,当在包含带有某些函数定义和枚举的嘲笑头时,错误再次浮出水面.因此,当此错误浮出水面时,它似乎确实是随机的.

对于如何解决此类问题的任何建议,我将感到非常高兴.

非常感谢您提出任何建议

解决方案

UDPATE到已编辑的问题

我看到了大量的动态分配(

旧答案:

  boost :: asio :: io_service io2;boost :: asio :: deadline_timer * t =新的boost :: asio :: deadline_timer(io2,boost :: posix_time :: seconds(1)); 

这仅仅是内存泄漏,但是在没有其他代码的情况下,它不可能导致 任何 症状,只是因为没有生成更多代码:在编译器资源管理器中实时运行

现在,所有其他观察结果都使您感到怀疑.没错!

我无法仅在独立的源文件中重现该错误.

这是关键.您的代码中有未定义的行为.它可能与计时器有关,也可能与计时器无关,但是此实例肯定不是引起的.

该代码的一个明显问题是内存泄漏,以及您首先进行手动分配的事实.这为终身问题打开了大门.

例如可以想象

  • 您在函数中有以下几行, io2 超出了范围,并且时间保留了对它的陈旧引用.

    实际上,这直接对应于范围后使用堆栈".检测

  • 许多其他情况,假设您也在某些地方 t-> async_wait()

从侧面观察到, io2 暗示您使用两个io服务(为什么?).除了所有这些,我希望您在真实的代码中使用更好的名称,因为在io2,i,m3,t等海洋中很容易迷失方向:

I have been stuck on a really wierd bug with Boost Deadline_timer for the last days. Desktop: Ubuntu 18.04 Boost: v1.65.01

When I create a new deadline_timer within the constructor of my class AddressSanitizer catches a stack-buffer-overflow coming from inside the Boost libraries.

I have a few observations:

  • I also notice that something is wrong without AddressSanitizer by that either the timer timeouts all the time becauce expiry_time is negative, or never expires. So it seems as if someplace someone is changing that memory region.
  • The class I am working with is quite big and is using the same Boost io_service to send data over UDP.
  • I am not able to reproduce the bug in just a standalone source file.
  • When I remove code to isolate the issue the issue remains no matter how much code I remove. I have gone down to a just a main filecreate a io_service and a deadline_timer and it stills throws that error. If I duplicate that in another file and duplicate the CMakeLists entry I am still not able to reproduce it.

The structure of the class is not very complicated and here is an example class which essentially does the same udp_timer.hpp

#include "boost/asio.hpp"


class UdpTimer {
    public:
        UdpTimer();
        ~UdpTimer();
        void run();

        void timer_callback(const boost::system::error_code &e);
        void udp_callback(const boost::system::error_code &e, size_t bytes_recvd);
        boost::asio::io_service io;
    
    private:
        boost::asio::ip::udp::socket *socket;
        boost::asio::ip::udp::endpoint *ep;
        boost::asio::deadline_timer *timer;
        char recv_buf[2048];
        unsigned int tot_bytes_recved;
};

udp_timer.cpp

#include "udp_timer.hpp"
#include "boost/bind.hpp"
#include <iostream>

UdpTimer::UdpTimer() {
    // Set up UDP part
  ep = new boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30042);
  socket = new boost::asio::ip::udp::socket(io, *ep);
  socket->async_receive_from(
    boost::asio::buffer(recv_buf, 2048), *ep,
      boost::bind(&UdpTimer::udp_callback, this,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred)
  );

  tot_bytes_recved = 0;

  timer = new boost::asio::deadline_timer(io, boost::posix_time::seconds(1));
  timer->async_wait(boost::bind(&UdpTimer::timer_callback, this, boost::asio::placeholders::error));
}

UdpTimer::~UdpTimer() {
    delete ep;
    delete socket;
    delete timer;
}

void UdpTimer::run() {
    io.run(); // Never returns
}


// Timer callback. Print info and reset timer
void UdpTimer::timer_callback(const boost::system::error_code &e) {       
    if (e) return;
    static int count = 0;
    std::cout <<"Timer Callback #" <<count++ <<"Bytes received = " <<tot_bytes_recved <<std::endl;
    std::cout <<recv_buf <<std::endl;

    timer->expires_from_now(boost::posix_time::seconds(1));
    timer->async_wait(boost::bind(&UdpTimer::timer_callback, this, boost::asio::placeholders::error));
}

// Udp callback. Update bytes received count
void UdpTimer::udp_callback(const boost::system::error_code &e, size_t bytes_recvd) {
    if (e) return;

    tot_bytes_recved += bytes_recvd;

    socket->async_receive_from(
    boost::asio::buffer(recv_buf, 2048), *ep,
      boost::bind(&UdpTimer::udp_callback, this,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred)
  );
}


int main(void)  {
    UdpTimer udp_timer;
    udp_timer.run();
}

This placed inside the program is enough to generate that error.

=================================================================
==20441==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe4a7621d0 at pc 0x55d73239950c bp 0x7ffe4a761f50 sp 0x7ffe4a761f40
WRITE of size 16 at 0x7ffe4a7621d0 thread T0
    #0 0x55d73239950b in boost::date_time::base_time<boost::posix_time::ptime, boost::date_time::split_timedate_system<boost::posix_time::posix_time_system_config> >::base_time(boost::gregorian::date const&, boost::posix_time::time_duration const&, boost::date_time::dst_flags) (/home/erl/dev/test/build/prog_ins+0x61950b)
    #1 0x55d732396495 in boost::posix_time::ptime::ptime(boost::gregorian::date, boost::posix_time::time_duration) /usr/include/boost/date_time/posix_time/ptime.hpp:40
    #2 0x55d7323d4855 in boost::date_time::microsec_clock<boost::posix_time::ptime>::create_time(tm* (*)(long const*, tm*)) /usr/include/boost/date_time/microsec_time_clock.hpp:116
    #3 0x55d7323d12f6 in boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time() /usr/include/boost/date_time/microsec_time_clock.hpp:76
    #4 0x55d7323cb501 in boost::asio::time_traits<boost::posix_time::ptime>::now() /usr/include/boost/asio/time_traits.hpp:48
    #5 0x55d7323db197 in boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::expires_from_now(boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::implementation_type&, boost::posix_time::time_duration const&, boost::system::error_code&) (/home/erl/dev/test/build/prog_ins+0x65b197)
    #6 0x55d7323d6a25 in boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> >::expires_from_now(boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::implementation_type&, boost::posix_time::time_duration const&, boost::system::error_code&) /usr/include/boost/asio/deadline_timer_service.hpp:129
    #7 0x55d7323d2ca8 in boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> > >::basic_deadline_timer(boost::asio::io_service&, boost::posix_time::time_duration const&) /usr/include/boost/asio/basic_deadline_timer.hpp:187
    #8 0x55d7323b7f22 in InsHandler::InsHandler(InsConfig*, spdlog::logger*) /home/erl/dev/test/src/InsHandler.cpp:57
    #9 0x55d7323a3fb0 in main /home/erl/dev/test/src/prog_ins.cpp:74
    #10 0x7f369ed89bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #11 0x55d7322894d9 in _start (/home/erl/dev/test/build/prog_ins+0x5094d9)

Address 0x7ffe4a7621d0 is located in stack of thread T0 at offset 480 in frame
    #0 0x55d7323d426f in boost::date_time::microsec_clock<boost::posix_time::ptime>::create_time(tm* (*)(long const*, tm*)) /usr/include/boost/date_time/microsec_time_clock.hpp:80

  This frame has 10 object(s):
    [32, 34) '<unknown>'
    [96, 98) '<unknown>'
    [160, 162) '<unknown>'
    [224, 228) 'd'
    [288, 296) 't'
    [352, 360) 'td'
    [416, 424) '<unknown>'
    [480, 488) '<unknown>' <== Memory access at offset 480 partially overflows this variable
    [544, 560) 'tv'
    [608, 664) 'curr'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/erl/dev/test/build/prog_ins+0x61950b) in boost::date_time::base_time<boost::posix_time::ptime, boost::date_time::split_timedate_system<boost::posix_time::posix_time_system_config> >::base_time(boost::gregorian::date const&, boost::posix_time::time_duration const&, boost::date_time::dst_flags)
Shadow bytes around the buggy address:
  0x1000494e43e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000494e43f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
  0x1000494e4400: f1 f1 f8 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2 f2
  0x1000494e4410: f2 f2 f8 f2 f2 f2 f2 f2 f2 f2 04 f2 f2 f2 f2 f2
  0x1000494e4420: f2 f2 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2
=>0x1000494e4430: f2 f2 00 f2 f2 f2 f2 f2 f2 f2[00]f2 f2 f2 f2 f2
  0x1000494e4440: f2 f2 00 00 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00
  0x1000494e4450: 00 f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000494e4460: 00 00 00 00 f1 f1 f1 f1 00 f2 f2 f2 f2 f2 f2 f2
  0x1000494e4470: 00 f2 f2 f2 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000494e4480: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f2 f2
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==20441==ABORTING

From this error printout it seems as if there is a bug in the Boost library that writes 16 bytes to something that only 8 bytes were allocated to. But why should that surface so intermittently? Also I notice that we have a few words that are marked as stack-use-after-scope which is f8. Could that mean that we have another part of the program is using a pointer to a stack-allocated object after its out of scope?

Running with valgrind gives me this

==27251== Conditional jump or move depends on uninitialised value(s)
==27251==    at 0x578FA1: boost::date_time::int_adapter<long>::is_infinity() const (int_adapter.hpp:114)
==27251==    by 0x5772A9: boost::date_time::int_adapter<long>::is_special() const (int_adapter.hpp:131)
==27251==    by 0x5A1069: boost::date_time::counted_time_rep<boost::posix_time::millisec_posix_time_system_config>::is_special() const (time_system_counted.hpp:108)
==27251==    by 0x59FCD3: boost::date_time::counted_time_system<boost::date_time::counted_time_rep<boost::posix_time::millisec_posix_time_system_config> >::add_time_duration(boost::date_time::counted_time_rep<boost::posix_time::millisec_posix_time_system_config> const&, boost::posix_time::time_duration) (time_system_counted.hpp:226)
==27251==    by 0x59EA90: boost::date_time::base_time<boost::posix_time::ptime, boost::date_time::counted_time_system<boost::date_time::counted_time_rep<boost::posix_time::millisec_posix_time_system_config> > >::operator+(boost::posix_time::time_duration const&) const (time.hpp:163)
==27251==    by 0x59E46B: boost::asio::time_traits<boost::posix_time::ptime>::add(boost::posix_time::ptime const&, boost::posix_time::time_duration const&) (time_traits.hpp:57)
==27251==    by 0x5A1BEC: boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::expires_from_now(boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::implementation_type&, boost::posix_time::time_duration const&, boost::system::error_code&) (deadline_timer_service.hpp:161)
==27251==    by 0x5A0811: boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> >::expires_from_now(boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::implementation_type&, boost::posix_time::time_duration const&, boost::system::error_code&) (deadline_timer_service.hpp:129)
==27251==    by 0x59F20B: boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> > >::basic_deadline_timer(boost::asio::io_service&, boost::posix_time::time_duration const&) (basic_deadline_timer.hpp:187)
==27251==    by 0x59DA57: OutputTimer::OutputTimer(boost::asio::io_service*, unsigned int, boost::function<OutputStates ()>) (output_timer.cpp:5)
==27251==    by 0x5877D5: InsHandler::InsHandler(InsConfig*, spdlog::logger*) (InsHandler.cpp:57)
==27251==    by 0x57B149: main (senti_ins.cpp:74)
==27251==  Uninitialised value was created by a stack allocation
==27251==    at 0x59FB3C: boost::date_time::microsec_clock<boost::posix_time::ptime>::create_time(tm* (*)(long const*, tm*)) (microsec_time_clock.hpp:80)

I am really lost here. There is really no connection between the changes I make to the source code and the resulting behaviour. I am able to remove the error by removing an inclusion of a totally unrelated header file. But the error surfaces again when including a mock_header with some function definitions and enums. So it really seems to be random when this error surfaces.

I would be extremely happy for any advice on how to attack such a problem.

I am very grateful for any advice on this

解决方案

UDPATE to the edited question

I see loads of dynamic allocation (Why should C++ programmers minimize use of 'new'?).

I see repeated magic constants (1s, 2048), failure to NUL-terminate the recv_buf and then treating it as a C string, swallowing errors.

Removing all these:

Live On Coliru

Live On Wandbox

  • udp_timer.h

     //#define BOOST_BIND_NO_PLACEHOLDERS
     #include <boost/asio.hpp>
    
     using boost::asio::ip::udp;
     using namespace std::chrono_literals;
    
     class UdpTimer {
       public:
         UdpTimer();
         void run();
    
       private:
         using error_code = boost::system::error_code;
         void timer_callback(error_code e);
         void udp_callback(error_code e, size_t bytes_recvd);
    
         void do_recv();
         void do_timer();
    
         boost::asio::io_service io;
         udp::endpoint ep { {}, 30042 };
         udp::socket socket { io, ep };
         boost::asio::steady_timer timer { io };
    
         std::array<char, 2048> recv_buf{};
         unsigned int tot_bytes_recved = 0;
     };
    

  • udp_timer.cpp

     #include "udp_timer.hpp"
     using namespace boost::asio::placeholders;
     #include <boost/bind/bind.hpp>
     #include <iostream>
     #include <iomanip>
    
     UdpTimer::UdpTimer() {
         do_recv();
         do_timer();
     }
    
     void UdpTimer::do_recv() {
         socket.async_receive_from(boost::asio::buffer(recv_buf), ep,
             boost::bind(&UdpTimer::udp_callback, this, error, bytes_transferred));
     }
    
     void UdpTimer::do_timer() {
         timer.expires_from_now(1s);
         timer.async_wait(boost::bind(&UdpTimer::timer_callback, this, error));
     }
    
     void UdpTimer::run() {
         io.run(); // Never returns
     }
    
     // Timer callback. Print info and reset timer
     void UdpTimer::timer_callback(error_code e)
     {
         if (e) {
             std::cout << "timer_callback: " << e.message() << std::endl;
             return;
         }
    
         static int count = 0;
         std::cout << "Timer Callback #" << count++
                   << " Bytes received = " << tot_bytes_recved << std::endl
                   << " Last received: " << std::quoted(recv_buf.data()) << std::endl;
    
         do_timer();
     }
    
     // Udp callback. Update bytes received count
     void UdpTimer::udp_callback(error_code e, size_t bytes_recvd) {
         if (e) {
             std::cout << "timer_callback: " << e.message() << std::endl;
             recv_buf[0] = '\0';
             return;
         }
    
         // because you want to print the buffer, you will also want to make sure it
         // is actually NUL terminated
         assert(bytes_recvd < recv_buf.size());
         recv_buf[bytes_recvd] = '\0';
         tot_bytes_recved += bytes_recvd;
    
         do_recv();
     }
    

  • main.cpp

     int main()
     {
         UdpTimer udp_timer;
         udp_timer.run();
     }
    

Running Demo, with ASAN+UBSAN enabled

OLD ANSWER:

boost::asio::io_service io2;
boost::asio::deadline_timer* t = new boost::asio::deadline_timer(io2, boost::posix_time::seconds(1)); 

This is merely a memory leak, but in the absence of other code it cannot possibly lead to any symptom, simply because no more code is generated: Live On Compiler Explorer

Now all the other observations make you suspicious. And rightfully so!

I am not able to reproduce the bug in just a standalone source file.

This is the key. There is Undefined Behaviour in your code. It may or may not have something to do with the timer, but it certainly isn't caused by this instantiation.

One obvious problem with the code is the memory leak, and the fact that you're doing manual allocation in the first place. This opens up the door for lifetime issues.

E.g. it is conceivable that

  • you have these lines in a function, the io2 goes out of scope and the time holds a stale reference to it.

    In fact this directly corresponds to the "stack-use-after-scope" detection

  • many other scenarios assuming that you also t->async_wait() somehwere

Side observations are that io2 implies that you use two io services (why?). Besides all of this I hope you use better names in your real code, because it's really easy to get lost in a sea of io2, i, m3, t etc :)

这篇关于提高截止时间_计时器导致堆栈缓冲区溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆