Как заставить компилятор gcc не оптимизировать вызов стандартной функции библиотеки, такой как printf?
Из любопытства мне было интересно, есть ли способ, которым gcc не оптимизирует вызовы функций?
В сгенерированном коде сборки функция printf заменяется на putchar. Это случается даже с настройками по умолчанию -O0
минимальный флаг оптимизации.
#include <stdio.h>
int main(void) {
printf("a");
return 0;
}
( Godbolt показывает, что GCC9 делает это, clang8 оставляет это без изменений.)
1 ответ
Использование -fno-builtin
отключить все замены и встраивание стандартных функций Си с эквивалентами.
Или использовать -fno-builtin-FUNCNAME
для конкретной функции, как -fno-builtin-printf
,
По умолчанию некоторые часто используемые стандартные функции C обрабатываются как встроенные функции, аналогично __builtin_popcount
, Обработчик для printf заменяет его на putchar или put, если это возможно. https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
Детали реализации оператора C, такие как printf("a")
по умолчанию не считаются видимым побочным эффектом, поэтому не сохраняются. Вы все еще можете установить точку останова на сайте вызова и войти в функцию (по крайней мере, в asm или в исходном режиме, если у вас установлены отладочные символы).
Чтобы отключить другие виды оптимизации для одной функции, см. __attribute__((optimize(0)))
на функции или #pragma GCC optimize
, Но будьте осторожны:
optimize
Атрибут должен использоваться только для целей отладки. Это не подходит в производственном коде.
Вы не можете отключить все оптимизации. Некоторая оптимизация присуща тому, как gcc трансформируется через внутреннее представление на пути к asm. См. Отключить все параметры оптимизации в GCC.
например, даже в -O0
GCC будет оптимизировать x / 10
к мультипликативному обратному.
Он по-прежнему сохраняет все в памяти между операторами C (для последовательной отладки; вот что -O0
действительно значит); У gcc нет "полностью тупого" режима, который пытается транслитерировать C в asm настолько наивно, насколько это возможно. использованиеtcc
для этого. Clang и ICC с-O0
несколько более буквальны, чем gcc, как и режим отладки MSVC.
Обратите внимание, что-g
никогда не влияет на генерацию кода, только на выданные метаданные. GCC использует другие варианты (в основном -O
, -f*
, а также -m*
) для управления Code-Gen, так что вы всегда можете безопасно включить -g
без ущерба для производительности, кроме больших двоичных файлов. Это не режим отладки (это -O0
), это просто символы отладки.