防止 gcc 将 printf 优化为 puts
Prevent gcc from optimizing printf into puts
这是我的测试代码:
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
很简单,我用gcc -o helloworld helloworld.c
编译了它(我也试过-g
)。
但是当我objdump -tT helloworld
时,输出是:
helloworld: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 abi-note.c
000000000000039c l O .note.ABI-tag 0000000000000020 __abi_tag
0000000000000000 l df *ABS* 0000000000000000 init.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000001070 l F .text 0000000000000000 deregister_tm_clones
00000000000010a0 l F .text 0000000000000000 register_tm_clones
00000000000010e0 l F .text 0000000000000000 __do_global_dtors_aux
0000000000004030 l O .bss 0000000000000001 completed.0
0000000000003df0 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry
0000000000001130 l F .text 0000000000000000 frame_dummy
0000000000003de8 l O .init_array 0000000000000000 __frame_dummy_init_array_entry
0000000000000000 l df *ABS* 0000000000000000 helloworld.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
000000000000211c l O .eh_frame 0000000000000000 __FRAME_END__
0000000000000000 l df *ABS* 0000000000000000
0000000000003df0 l .init_array 0000000000000000 __init_array_end
0000000000003df8 l O .dynamic 0000000000000000 _DYNAMIC
0000000000003de8 l .init_array 0000000000000000 __init_array_start
0000000000002014 l .eh_frame_hdr 0000000000000000 __GNU_EH_FRAME_HDR
0000000000004000 l O .got.plt 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000001000 l F .init 0000000000000000 _init
00000000000011d0 g F .text 0000000000000005 __libc_csu_fini
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000004020 w .data 0000000000000000 data_start
0000000000000000 F *UND* 0000000000000000 puts@GLIBC_2.2.5
0000000000004030 g .data 0000000000000000 _edata
00000000000011d8 g F .fini 0000000000000000 .hidden _fini
0000000000000000 F *UND* 0000000000000000 __libc_start_main@GLIBC_2.2.5
0000000000004020 g .data 0000000000000000 __data_start
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000004028 g O .data 0000000000000000 .hidden __dso_handle
0000000000002000 g O .rodata 0000000000000004 _IO_stdin_used
0000000000001160 g F .text 0000000000000065 __libc_csu_init
0000000000004038 g .bss 0000000000000000 _end
0000000000001040 g F .text 000000000000002f _start
0000000000004030 g .bss 0000000000000000 __bss_start
0000000000001139 g F .text 000000000000001a main
0000000000004030 g O .data 0000000000000000 .hidden __TMC_END__
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w F *UND* 0000000000000000 __cxa_finalize@GLIBC_2.2.5
DYNAMIC SYMBOL TABLE:
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 puts
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000000000 w D *UND* 0000000000000000 __gmon_start__
0000000000000000 w D *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize
如您所见,没有 printf
符号...出了什么问题...?
有趣的是,虽然我没有使用 puts
,但我们可以在那里看到 puts
。
然后我找到了this
好的,如果我将 printf 与文字字符串一起使用,我得到的是 puts 而不是 printf,因为不需要使用它。
所以我用 -O0
再次编译了它,但 gcc 仍然优化它。
我应该怎么做才能阻止 gcc 对其进行优化?
添加一个简单的说明符:
printf("Hello, world%c", '\n');
对于gcc,可以使用命令行选项
-fno-builtin-printf
以便编译器不会将函数 printf
识别为 built-in function(这允许进一步优化,例如将其重定向到 puts
)。
或者您可以使用
-fno-builtin
以便编译器不会将任何函数识别为内置函数,以 __builtin_
前缀开头的函数除外。
不过,我一般不建议这样做,因为这可能会对性能产生负面影响。只有在有特殊原因时才应该这样做。
这是我的测试代码:
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
很简单,我用gcc -o helloworld helloworld.c
编译了它(我也试过-g
)。
但是当我objdump -tT helloworld
时,输出是:
helloworld: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 abi-note.c
000000000000039c l O .note.ABI-tag 0000000000000020 __abi_tag
0000000000000000 l df *ABS* 0000000000000000 init.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000001070 l F .text 0000000000000000 deregister_tm_clones
00000000000010a0 l F .text 0000000000000000 register_tm_clones
00000000000010e0 l F .text 0000000000000000 __do_global_dtors_aux
0000000000004030 l O .bss 0000000000000001 completed.0
0000000000003df0 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry
0000000000001130 l F .text 0000000000000000 frame_dummy
0000000000003de8 l O .init_array 0000000000000000 __frame_dummy_init_array_entry
0000000000000000 l df *ABS* 0000000000000000 helloworld.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
000000000000211c l O .eh_frame 0000000000000000 __FRAME_END__
0000000000000000 l df *ABS* 0000000000000000
0000000000003df0 l .init_array 0000000000000000 __init_array_end
0000000000003df8 l O .dynamic 0000000000000000 _DYNAMIC
0000000000003de8 l .init_array 0000000000000000 __init_array_start
0000000000002014 l .eh_frame_hdr 0000000000000000 __GNU_EH_FRAME_HDR
0000000000004000 l O .got.plt 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000001000 l F .init 0000000000000000 _init
00000000000011d0 g F .text 0000000000000005 __libc_csu_fini
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000004020 w .data 0000000000000000 data_start
0000000000000000 F *UND* 0000000000000000 puts@GLIBC_2.2.5
0000000000004030 g .data 0000000000000000 _edata
00000000000011d8 g F .fini 0000000000000000 .hidden _fini
0000000000000000 F *UND* 0000000000000000 __libc_start_main@GLIBC_2.2.5
0000000000004020 g .data 0000000000000000 __data_start
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000004028 g O .data 0000000000000000 .hidden __dso_handle
0000000000002000 g O .rodata 0000000000000004 _IO_stdin_used
0000000000001160 g F .text 0000000000000065 __libc_csu_init
0000000000004038 g .bss 0000000000000000 _end
0000000000001040 g F .text 000000000000002f _start
0000000000004030 g .bss 0000000000000000 __bss_start
0000000000001139 g F .text 000000000000001a main
0000000000004030 g O .data 0000000000000000 .hidden __TMC_END__
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w F *UND* 0000000000000000 __cxa_finalize@GLIBC_2.2.5
DYNAMIC SYMBOL TABLE:
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 puts
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000000000 w D *UND* 0000000000000000 __gmon_start__
0000000000000000 w D *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize
如您所见,没有 printf
符号...出了什么问题...?
有趣的是,虽然我没有使用 puts
,但我们可以在那里看到 puts
。
然后我找到了this
好的,如果我将 printf 与文字字符串一起使用,我得到的是 puts 而不是 printf,因为不需要使用它。
所以我用 -O0
再次编译了它,但 gcc 仍然优化它。
我应该怎么做才能阻止 gcc 对其进行优化?
添加一个简单的说明符:
printf("Hello, world%c", '\n');
对于gcc,可以使用命令行选项
-fno-builtin-printf
以便编译器不会将函数 printf
识别为 built-in function(这允许进一步优化,例如将其重定向到 puts
)。
或者您可以使用
-fno-builtin
以便编译器不会将任何函数识别为内置函数,以 __builtin_
前缀开头的函数除外。
不过,我一般不建议这样做,因为这可能会对性能产生负面影响。只有在有特殊原因时才应该这样做。