Boost::Signals2 带有 lambda 表达式的插槽在 arm32 上使用 gcc6 失败
Boost::Signals2 slot with lambda expression fails using gcc6 on arm32
我从一位同事那里收到了以下代码,使用 Boost::Signal2 和 lambda 表达式分解到了最低限度。它使用 g++ 6.x 和 g++ 5.4.1 编译(后者带有参数 -std=c++11)。
它应该打印 i: 5(应该是 5)
在这样的系统上使用 arm32 (arm-cortexa15-linux-gnueabihf-g++) 和 运行ning 的 gcc 6.4.1(或 6.1.1)交叉编译器,输出是i:0(应该是5)
其他架构 (x86_64) 和编译器 (gcc 5.4.1) 按预期工作。
当我将代码更改为使用信号而不是插槽时,一切正常。
我的问题是:
这段代码真的应该可靠地输出 i: 5(应该是 5),还是这段代码有错误并且只是偶然工作?
或者ARM32 gcc6编译器有bug? (海湾合作委员会 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)
这看起来像是一个错误。
你能减少reproducer吗?说,
如果禁用优化会怎样
如果删除 LogBuffer 会怎样?
如果移除插槽并将其用作信号会怎样
如果保留信号并直接调用 lambda 会怎样?
如果在创建插槽之前调用 lambda 会发生什么情况
如果你甚至不创建插槽,直接调用 lambda 会怎样?
如果你进一步移除信号2会发生什么header.
如果您在断言处理程序中终止会发生什么(也许您在 std::cout
尚未初始化//可用时获得断言)
如果你把它缩减到最简单的核心,但仍然失败,你至少会知道是在 Boost 还是 GCC 上提交错误
这是我已经做过的:
- -O0,-O1: bug 没有出现 i: 5 (应该是 5)
- -O2:错误出现 0(应该是 5)
- 删除日志缓冲区:5(应该是 5)
- 使用信号信号:0 应该是 5
- 直接调用lambda(5应该是5)
- 调用插槽后使用 i(例如打印):5(应该是 5)
- using i[100]: 第一个元素变为零,其他元素不受影响
- 使用 x86_64 编译器:5 应该是 5
其他人会跟进。我不确定如何轻松删除信号 2 header
莱纳
我从一位同事那里收到了以下代码,使用 Boost::Signal2 和 lambda 表达式分解到了最低限度。它使用 g++ 6.x 和 g++ 5.4.1 编译(后者带有参数 -std=c++11)。
它应该打印 i: 5(应该是 5)
在这样的系统上使用 arm32 (arm-cortexa15-linux-gnueabihf-g++) 和 运行ning 的 gcc 6.4.1(或 6.1.1)交叉编译器,输出是i:0(应该是5)
其他架构 (x86_64) 和编译器 (gcc 5.4.1) 按预期工作。
当我将代码更改为使用信号而不是插槽时,一切正常。
我的问题是:
这段代码真的应该可靠地输出 i: 5(应该是 5),还是这段代码有错误并且只是偶然工作?
或者ARM32 gcc6编译器有bug? (海湾合作委员会 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)
这看起来像是一个错误。
你能减少reproducer吗?说,
如果禁用优化会怎样
如果删除 LogBuffer 会怎样?
如果移除插槽并将其用作信号会怎样
如果保留信号并直接调用 lambda 会怎样?
如果在创建插槽之前调用 lambda 会发生什么情况
如果你甚至不创建插槽,直接调用 lambda 会怎样?
如果你进一步移除信号2会发生什么header.
如果您在断言处理程序中终止会发生什么(也许您在
std::cout
尚未初始化//可用时获得断言)
如果你把它缩减到最简单的核心,但仍然失败,你至少会知道是在 Boost 还是 GCC 上提交错误
这是我已经做过的:
- -O0,-O1: bug 没有出现 i: 5 (应该是 5)
- -O2:错误出现 0(应该是 5)
- 删除日志缓冲区:5(应该是 5)
- 使用信号信号:0 应该是 5
- 直接调用lambda(5应该是5)
- 调用插槽后使用 i(例如打印):5(应该是 5)
- using i[100]: 第一个元素变为零,其他元素不受影响
- 使用 x86_64 编译器:5 应该是 5
其他人会跟进。我不确定如何轻松删除信号 2 header
莱纳