Как заставить компилятор 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), это просто символы отладки.

Другие вопросы по тегам