отключить возврат-оптимизацию для одной функции

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

X foo( void * u, void * v);
  • foo () реализован на ассемблере (i386)
  • адрес возвращаемого значения типа X передается как скрытый параметр в foo ()

  • если тестовый код скомпилирован с -O0, код работает как положено

  • если скомпилировано с ошибкой сегментации -O3 (возвращаемое значение было оптимизировано)
  • если скомпилировано с -O3 -fno-elide-constructors, код снова работает как положено

Как можно принудительно заставить компилятор не добавлять 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 был оптимизирован, и реализация пытается получить доступ к первому аргументу
, который является нулевым указателем.

2

Решение

Вы также можете установить уровень оптимизации для отдельной функции в 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
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]