【问题标题】:Boost::Signals2 slot with lambda expression fails using gcc6 on arm32带有 lambda 表达式的 Boost::Signals2 插槽在 arm32 上使用 gcc6 失败
【发布时间】:2018-02-15 15:46:19
【问题描述】:

我从一位同事那里收到以下代码,使用 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编译器有bug? (gcc 5 作品)

代码:

#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)

【问题讨论】:

    标签: c++ boost arm signals gcc6


    【解决方案1】:

    这看起来像一个错误。

    你能减少复制器吗?说吧,

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

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

    • 如果您移除插槽并将其用作信号会发生什么

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

    • 如果在创建槽之前调用 lambda 会发生什么

    • 如果你甚至不创建槽,直接调用 lambda 会发生什么?

    • 如果您还删除了 signals2 标头,会发生什么情况。

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

    如果你把它减少到最简单的内核并且仍然出现故障,你至少会知道是在 Boost 还是 GCC 上提交错误

    【讨论】:

      【解决方案2】:

      这是我已经做过的:

      1. -O0, -O1: bug 没有出现 i: 5(应该是 5)
      2. -O2:错误显示为 0(应为 5)
      3. 删除日志缓冲区:5(应该是 5)
      4. 使用信号 Signal: 0 应该是 5
      5. 直接调用 lambda(5 应该是 5)
      6. 在调用 slot 后使用 i(例如打印):5(应该是 5)
      7. 使用 i[100]:第一个元素变为零,其他元素不受影响
      8. 使用 x86_64 编译器:5 应该是 5

      其他人将跟随。我不确定如何轻松删除 signals2 标头

      莱纳

      【讨论】:

      • 这不是答案 - 您应该将其添加到问题中 - 这是问题的一部分
      猜你喜欢
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-19
      • 2020-09-04
      相关资源
      最近更新 更多