struct X {
void * a;
void * b;
};
X foo( void * u, void * v);
类型X的返回值的地址作为隐藏参数传递给foo()
如果使用-O0编译测试代码,则代码按预期工作
如何强制编译器不为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已经过优化,实现尝试访问第一个参数 ,这是一个空指针。
答案 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