3
struct X {
  void * a;
  void * b;
};

X foo( void * u, void * v);
  • foo() 在汇编器中实现 (i386)
  • X 类型的返回值的地址作为隐藏参数传递给 foo()

  • 如果使用 -O0 编译测试代码,则代码按预期工作

  • 如果使用 -O3 编译发生分段错误(返回值已优化)
  • 如果使用 -O3 -fno-elide-constructors 编译,代码将再次按预期工作

如何强制编译器不只为 foo() 添加 RVO(也就是不强制 -fno-elide-constructors)?

Update1:​​代码必须适用于任意编译器(至少 gcc、clang、msvc),示例代码:

void * vp = bar();
X x = foo( vp, 0);
x = foo( x.a, 0);
x = foo( x.a, 0);

Update2:问题是,编译器优化了 x 的实例

X x = foo( vp, 0);
x = foo( x.a, 0);
x = foo( x.a, 0)

或者

X x1 = foo( vp, 0);
X x2 = foo( x1.a, 0);
X x3 = foo( x2.a, 0)

没关系。例如,发生段错误是因为

X x2 = foo( x1.a, 0);

x1 被优化,实现尝试访问第一个参数,它是一个空指针。

4

1 回答 1

7

您也可以在 GCC 中为单个函数设置优化级别:

X foo(void *u, void *v) __attribute__((optimize("no-elide-constructors");

optimize 属性用于指定使用与命令行中指定的不同的优化选项来编译函数。参数可以是数字或字符串。数字被假定为优化级别。以 O 开头的字符串被假定为优化选项,而其他选项被假定与 -f 前缀一起使用。您还可以使用 '#pragma GCC optimize' pragma 设置影响多个函数的优化选项。有关“#pragma GCC optimize”编译指示的详细信息,请参阅函数特定选项编译指示。

例如,这可以用于使用更积极的优化选项编译频繁执行的函数,从而生成更快和更大的代码,而其他函数可以使用不那么积极的选项进行编译。

https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html

您也可以尝试#pragma变体

#pragma GCC push_options
#pragma GCC optimize ("no-elide-constructors")

X foo(void *u, void *v);

#pragma GCC pop_options
于 2015-11-02T10:24:20.267 回答