"this" lambda 捕获的错误。 GCC 编译器错误?
"this" captured by lambda is incorrect. GCC compiler bug?
最近几天,我一直在调试一个涉及 C++ 中的 lambda 的奇怪问题。我已将问题简化为以下症状:
this
指针在 lambda 中损坏(注意:this
总是被复制捕获,所以 lambda 应该有它自己的 this
指针,指向App
对象)
- 仅当存在
std::cout
打印语句 并在创建 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.
这可能是编译器错误吗?
听起来像以下编译器错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77933(仅影响使用 O1 优化或更高优化生成的代码)。
这似乎是 gcc 6.2 中的编译器错误,请参阅:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77686
解决方法:
- 使用
-fno-schedule-insns2
标志(正如 gbmhunter 所指出的,请参阅下面的评论)。
- 不要使用
-O2
优化或更高。
最近几天,我一直在调试一个涉及 C++ 中的 lambda 的奇怪问题。我已将问题简化为以下症状:
this
指针在 lambda 中损坏(注意:this
总是被复制捕获,所以 lambda 应该有它自己的this
指针,指向App
对象)- 仅当存在
std::cout
打印语句 并在创建 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.
这可能是编译器错误吗?
听起来像以下编译器错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77933(仅影响使用 O1 优化或更高优化生成的代码)。
这似乎是 gcc 6.2 中的编译器错误,请参阅:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77686
解决方法:
- 使用
-fno-schedule-insns2
标志(正如 gbmhunter 所指出的,请参阅下面的评论)。 - 不要使用
-O2
优化或更高。