Слот Boost::Signals2 с лямбда-выражением завершается неудачно, используя gcc6 на arm32

Я получил следующий код от коллеги, разбитый до минимума, используя выражения Boost::Signal2 и lambda. Компилируется с g++ 6.x и g++ 5.4.1 (последний с аргументом -std= C++ 11).

Должно быть напечатано i: 5 (должно быть 5)

Используя кросс-компилятор gcc 6.4.1 (или 6.1.1) для arm32 (arm-cortexa15-linux-gnueabihf-g++) и работающий в такой системе, получим i: 0 (должно быть 5)

Другие архитектуры (x86_64) и компиляторы (gcc 5.4.1) работают как положено.

Когда я перехожу на код, чтобы использовать сигнал вместо слота, все в порядке.

Мои вопросы:

  1. Действительно ли этот код должен надежно выводить i: 5 (должно быть 5), или этот код глючит и работает только случайно?

  2. Или есть ошибка в компиляторе ARM32 gcc6? (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)

2 ответа

Решение

Это похоже на ошибку.

Вы можете уменьшить репродуктор? Сказать,

  • что произойдет, если вы отключите оптимизацию

  • что произойдет, если вы удалите LogBuffer?

  • Что произойдет, если вы удалите слот и использовать его в качестве сигнала

  • Что произойдет, если вы сохраните сигналы и просто вызовете лямбду напрямую?

  • Что произойдет, если вы вызываете лямбду перед созданием слота

  • Что произойдет, если вы даже не создадите слот и не вызовете лямбду напрямую?

  • Что произойдет, если вы также удалите заголовок signal2.

  • Что произойдет, если вы завершите работу с обработчиками утверждений (возможно, вы получаете утверждения в то время, когда std::cout еще не инициализировано // доступно)

Если вы уменьшите его до максимально простого ядра и все равно будете иметь сбой, вы по крайней мере будете знать, следует ли сообщать об ошибке в Boost или GCC.

Это то, что я уже сделал:

  1. -O0, -O1: ошибка не отображается i: 5 (должно быть 5)
  2. -O2: ошибка показывает 0 (должно быть 5)
  3. удалить Logbuffer: 5 (должно быть 5)
  4. используя сигнал Сигнал: 0 должно быть 5
  5. вызов лямбды напрямую (5 должно быть 5)
  6. использование i после вызова слота (например, печать): 5 (должно быть 5)
  7. используя i[100]: первый элемент становится нулем, другие не затрагиваются
  8. с использованием компилятора x86_64: 5 должно быть 5

Другие будут следовать. Я не уверен, как я могу легко удалить заголовок signal2

Райнер

Другие вопросы по тегам