如何让 gcc 编译器不优化像 printf 这样的标准库函数调用?
How to get the gcc compiler to not optimize a standard library function call like printf?
出于好奇,我想知道是否有任何方法可以让 gcc 不优化任何函数调用?
在生成的汇编代码中,printf函数被putchar替换。即使使用默认的 -O0
最小优化标志也会发生这种情况。
#include <stdio.h>
int main(void) {
printf("a");
return 0;
}
(Godbolt 显示 GCC9 正在做,clang8 保持不变。)
使用 -fno-builtin
禁用标准 C 函数的所有替换和内联。
或使用 -fno-builtin-FUNCNAME
作为特定功能,例如 -fno-builtin-printf
。
默认情况下,一些 commonly-used 标准 C 函数作为内置函数处理,类似于 __builtin_popcount
。如果可能,printf 的处理程序将其替换为 putchar 或 puts。 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
默认情况下,像 printf("a")
这样的 C 语句的实现细节不被视为可见的 side-effect,因此不会被保留。您仍然可以在 call-site 处设置断点并进入函数(至少在 asm 中,或者如果安装了调试符号,则在源代码模式下)。
要禁用单个函数的其他类型的优化,请参阅 __attribute__((optimize(0)))
on a function 或 #pragma GCC optimize
。但要注意:
The optimize
attribute should be used for debugging purposes only. It is not suitable in production code.
您无法禁用所有 优化。一些优化是 gcc 通过内部表示转换为 asm 的方式所固有的。参见 Disable all optimization options in GCC。
例如即使在 -O0
gcc 也会将 x / 10
优化为乘法逆。
它仍然将 C 语句之间的所有内容存储到内存中(为了一致的调试;that's what -O0
really means); gcc 没有 "fully dumb" 模式试图尽可能天真地将 C 音译为 asm。为此使用 tcc
。 -O0
的 Clang 和 ICC 比 gcc 更直白一些,MSVC 调试模式也是如此。
请注意,-g
对 code-gen 没有 任何 影响,仅对发出的元数据有影响。 GCC 使用其他选项(主要是 -O
、-f*
和 -m*
)来控制 code-gen,因此您始终可以安全地启用 -g
而不会影响性能,除了更大的二进制文件。这不是 debug mode(即 -O0
),它只是 debug symbols.
出于好奇,我想知道是否有任何方法可以让 gcc 不优化任何函数调用?
在生成的汇编代码中,printf函数被putchar替换。即使使用默认的 -O0
最小优化标志也会发生这种情况。
#include <stdio.h>
int main(void) {
printf("a");
return 0;
}
(Godbolt 显示 GCC9 正在做,clang8 保持不变。)
使用 -fno-builtin
禁用标准 C 函数的所有替换和内联。
或使用 -fno-builtin-FUNCNAME
作为特定功能,例如 -fno-builtin-printf
。
默认情况下,一些 commonly-used 标准 C 函数作为内置函数处理,类似于 __builtin_popcount
。如果可能,printf 的处理程序将其替换为 putchar 或 puts。 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
默认情况下,像 printf("a")
这样的 C 语句的实现细节不被视为可见的 side-effect,因此不会被保留。您仍然可以在 call-site 处设置断点并进入函数(至少在 asm 中,或者如果安装了调试符号,则在源代码模式下)。
要禁用单个函数的其他类型的优化,请参阅 __attribute__((optimize(0)))
on a function 或 #pragma GCC optimize
。但要注意:
The
optimize
attribute should be used for debugging purposes only. It is not suitable in production code.
您无法禁用所有 优化。一些优化是 gcc 通过内部表示转换为 asm 的方式所固有的。参见 Disable all optimization options in GCC。
例如即使在 -O0
gcc 也会将 x / 10
优化为乘法逆。
它仍然将 C 语句之间的所有内容存储到内存中(为了一致的调试;that's what -O0
really means); gcc 没有 "fully dumb" 模式试图尽可能天真地将 C 音译为 asm。为此使用 tcc
。 -O0
的 Clang 和 ICC 比 gcc 更直白一些,MSVC 调试模式也是如此。
请注意,-g
对 code-gen 没有 任何 影响,仅对发出的元数据有影响。 GCC 使用其他选项(主要是 -O
、-f*
和 -m*
)来控制 code-gen,因此您始终可以安全地启用 -g
而不会影响性能,除了更大的二进制文件。这不是 debug mode(即 -O0
),它只是 debug symbols.