"这"由lambda捕获是不正确的。 GCC编译器错误?

时间:2017-06-29 16:28:36

标签: c++ c++11 lambda arm compiler-bug

在过去的几天里,我一直在调试一个涉及C ++中lambdas的奇怪问题。我已将问题减少到以下症状:

  • this指针在lambda内部被破坏(注意:this始终由副本捕获,因此lambda应该获得自己的this指针,它指向App对象)
  • 只有在出现std::cout print语句时才会出现,并且在创建lambda之前调用它。 print语句看似完全不相关(例如print" Hello!")。 printf()也表现出相同的行为。
  • 仅在交叉编译时发生
  • 使用x86架构的标准编译器编译并运行良好(参见example)。
  • 如果我在堆上创建lambda(并在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.

这可能是编译器错误吗?

2 个答案:

答案 0 :(得分:3)

听起来像以下编译器错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77933(仅影响使用O1优化或更高优化生成的代码)。

答案 1 :(得分:3)

这似乎是gcc 6.2中的编译器错误,请参阅:

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

解决方法:

  • 使用-fno-schedule-insns2标志(由gbmhunter指出,请参阅下面的评论)。
  • 请勿使用-O2优化或更高版本。