禁用一个函数的返回值优化

时间:2015-11-02 10:18:33

标签: c++ assembly return-value-optimization rvo nrvo

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)

没关系。例如,segfault发生是因为

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

x1已经过优化,实现尝试访问第一个参数 ,这是一个空指针。

1 个答案:

答案 0 :(得分:6)

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

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

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

     

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

     

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

您还可以尝试#pragma variant

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

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

#pragma GCC pop_options