"this", зафиксированное лямбдой, неверно. Ошибка компилятора GCC?

В течение последних нескольких дней я отлаживал странную проблему, связанную с lambdas на С++. Я уменьшил проблему до следующих симптомов:

  • Указатель this поврежден внутри лямбда (примечание: this всегда записывается копией, поэтому лямбда должна получить свой собственный указатель this, который указывает на App объект)
  • Это происходит только в том случае, если <<24 > присутствует и вызывается до создания лямбда. Оператор печати может казаться совершенно не связанным (например, печатать "Hello!" ). printf() также демонстрирует то же поведение.
  • Это происходит только при кросс-компиляции.
  • Он компилируется и отлично работает со стандартным компилятором для архитектуры x86 (см. пример).
  • Если я создаю лямбду в куче (и сохраняю указатель на нее внутри объекта App), ошибка не возникает.
  • Ошибка, если оптимизация отключена (т.е. если я устанавливаю флаг -O0). Это происходит, когда оптимизация установлена ​​на -O2.

Ниже приведен самый простой, компилируемый пример кода, который может возникнуть из-за проблемы.

#include <iostream>
#include <functional>

class App {

public:

    std::function<void*()> test_;

    void Run() {

        // Enable this line, ERROR is printed
        // Disable this line, app runs o.k.
        std::cout << "This print statement causes the bug below!" << std::endl;

        test_ = [this] () {
            return this;
        };

        void* returnedThis = test_();
        if(returnedThis != this) {
            std::cout << "ERROR: 'this' returned from lambda (" << returnedThis 
                      << ") is NOT the same as 'this' (" << this << ") !?!?!?!?!"
                      << std::endl;
        } else {
            std::cout << "Program run successfully." << std::endl;
        }

    }
};

int main(void) {
    App app;
    app.Run();
}

При запуске на целевом устройстве я получаю следующий вывод:

This print statement causes the bug below!
ERROR: 'this' returned from lambda (0xbec92dd4) is NOT the same as 'this' 
(0xbec92c68) !?!?!?!?!

Если я попытаюсь разыменовать поврежденный this, я обычно получаю ошибку сегментации, именно так я обнаружил ошибку в первую очередь.

Настройки компилятора

arm-poky-linux-gnueabi-g++ -march=armv7-a -marm -mfpu=neon -std=c++14 \
-mfloat-abi=hard -mcpu=cortex-a9 \
--sysroot=/home/ghunter/sysroots/cortexa9hf-neon-poky-linux-gnueabi \
-O2 -pipe -g -feliminate-unused-debug-types

Настройки компоновщика

arm-poky-linux-gnueabi-ld \
--sysroot=/home/ghunter/sysroots/cortexa9hf-neon-poky-linux-gnueabi \
-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed

Версия компилятора

~$ arm-poky-linux-gnueabi-g++ --version

arm-poky-linux-gnueabi-g++ (GCC) 6.2.0
Copyright (C) 2016 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.

Может ли это быть ошибкой компилятора?

Ответы

Ответ 1

Это, похоже, ошибка компилятора в gcc 6.2, см.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77686

Обходные пути:

  • Используйте флаг -fno-schedule-insns2 (как указано gbmhunter, см. комментарий ниже).
  • Не используйте оптимизацию -O2 или выше.

Ответ 2

Похоже на следующую ошибку компилятора: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77933 (который генерирует только код, сгенерированный с оптимизацией O1 или выше).