使用arm32上的gcc6时,带有lambda表达式的Boost :: Signals2槽失败

时间:2018-02-15 15:46:20

标签: c++ boost arm signals gcc6

我使用Boost :: Signal2和lambda表达式从同事那里收到了以下代码,细分到最低限度。它用g ++ 6.x和g ++ 5.4.1编译(后者带参数-std = c ++ 11)。

应打印 i:5(应为5)

对于arm32(arm-cortexa15-linux-gnueabihf-g ++)使用gcc 6.4.1(或6.1.1)交叉编译器并在这样的系统上运行,输出 i:0(应为5) )

其他架构(x86_64)和编译器(gcc 5.4.1)按预期工作。

当我更改代码以使用信号而不是插槽时,一切正常。

我的问题是:

  1. 这段代码真的可靠地输出i:5(应该是5),还是这个代码有问题并只是偶然起作用?

  2. 或者ARM32 gcc6编译器中是否有错误? (gcc 5作品)

  3. 代码:

    #include <exception>
    #include <iostream>
    #include <boost/signals2.hpp>
    
    class LogBuffer : public std::streambuf
    {   
    public:
        LogBuffer()
        {   
        }   
    
        char m_buf[242 - 20];
    };  
    
    namespace boost
    {   
        void assertion_failed(char const * p_expr,
                              char const *,
                              char const *, long)
        {   
            std::cerr << "FAILED: " << p_expr << std::endl;
        }   
    
        void assertion_failed_msg(char const *,
                                  char const * msg,
                                  char const *,
                                  char const *, long)
        {   
            std::cerr << "FAILED: " << msg << std::endl;
        }   
    } // namespace boost
    
    void myfunction(void)
    {   
    
        {   
            LogBuffer b;
            std::cout << "LogBuffer size: " << sizeof(LogBuffer) << std::endl;
        }   
        int i=5;
        std::cout << i << std::endl;
        auto lambda = [i] { std::cerr << "i: " << i << " (should be 5)" << std::endl; };
        boost::signals2::signal<void()>::slot_type slot{lambda};
        slot();
    }   
    
    int main(int argc, char *argv[])
    {   
        myfunction();
    }   
    

    编译并运行提供以下输出:

    arm-cortexa15-linux-gnueabihf-g++ (GCC) 6.4.1 20170811
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    Linux fctj-4a 4.4.109-g68c6f3c-fsm4_axm #1 SMP PREEMPT Fri Feb 2 05:37:09 UTC 2018 armv7l GNU/Linux
    
    LogBuffer size: 256
    5
    i: 0 (should be 5)
    

2 个答案:

答案 0 :(得分:1)

这看起来像个错误。

你能减少复制吗?说,

  • 如果禁用优化会发生什么

  • 如果删除LogBuffer会发生什么?

  • 如果您移除插槽并将其用作信号

  • 会发生什么情况
  • 如果您保留信号并直接调用lambda会发生什么?

  • 如果在创建插槽

  • 之前调用lambda会发生什么
  • 如果您甚至不创建插槽,并直接调用lambda会发生什么?

  • 如果您进一步删除signals2标题会发生什么。

  • 如果你在断言处理程序中终止会发生什么(也许你在std::cout尚未初始化//可用时获得断言)

如果你把它减少到最简单的核心但仍然有失败,你至少会知道是否在Boost或GCC提交错误

答案 1 :(得分:0)

这就是我已经做过的事情:

  1. -O0,-O1:错误未显示i:5(应为5)
  2. -O2:bug显示0(应为5)
  3. 删除Logbuffer:5(应为5)
  4. 使用信号信号:0应为5
  5. 直接调用lambda(5应为5)
  6. 在调用插槽(例如打印)后使用i:5(应该是5)
  7. 使用i [100]:第一个元素变为零,其他元素不受影响
  8. 使用x86_64编译器:5应为5
  9. 其他人会跟随。我不确定如何轻松删除signals2标头

    莱纳