struct X {
void * a;
void * b;
};
X foo( void * u, void * v);
адрес возвращаемого значения типа X передается как скрытый параметр в foo ()
если тестовый код скомпилирован с -O0, код работает как положено
Как можно принудительно заставить компилятор не добавлять RVO только для foo () (иначе говоря, не вызывать -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 = 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 был оптимизирован, и реализация пытается получить доступ к первому аргументу
, который является нулевым указателем.
Вы также можете установить уровень оптимизации для отдельной функции в GCC:
X foo(void *u, void *v) __attribute__((optimize("no-elide-constructors");
Атрибут optimize используется для указания того, что функция должна быть скомпилирована с параметрами оптимизации, отличными от указанных в командной строке. Аргументы могут быть числами или строками. Числа предполагаются как уровень оптимизации. Предполагается, что строки, начинающиеся с O, являются опцией оптимизации, тогда как предполагается, что другие опции используются с префиксом -f. Вы также можете использовать прагму «#pragma GCC optimize» для настройки параметров оптимизации, которые влияют на более чем одну функцию. См. Прагмы параметров, специфичных для функций, для получения подробной информации о прагме «#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
Других решений пока нет …