如何阻止GCC从obj文件中的字符串文字中删除尾随换行符?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何阻止GCC从obj文件中的字符串文字中删除尾随换行符?相关的知识,希望对你有一定的参考价值。
在Linux下工作,我刚刚遇到了以下问题。 (当然,有人会给我答案,但到目前为止,我没有找到任何简单明了的答案:)
/*compile with gcc -o out.x hello.c*/
#include<stdio.h>
int main()
{
printf("Hello World2
");
printf("Hello World3
");
return 0;
}
在Linux下运行以下代码给出两个字符串但结尾字符是不同的:第一个输出以0x0d结尾,而第二个以0x0d,0x0a结尾。
这是由编译器(GCC)完成的,如obj文件中所示:
Contents of section .rodata:
400610 01000200 48656c6c 6f20576f 726c6432 ....Hello World2
400620 0d004865 6c6c6f20 576f726c 64330d0a ..Hello World3..
400630 2000 .
所以,问题是:
- 为什么?
- 我怎样才能避免这种“优化”(!?)
谢谢
在运行时创建格式化输出需要时间; printf
呼叫很慢。 GCC知道这一点,所以replaces是调用puts
的第一个函数。由于puts
自动添加
,GCC需要从字符串中删除
以进行补偿。
海湾合作委员会这样做是因为它认为printf
是built-in。因为这对字节输出甚至对write
的调用次数没有影响;我强烈建议保持原样。如果你想要禁用它,你可以使用can pass -fno-builtin-printf
,但唯一的效果是减慢你的代码,因为它试图不必要地格式化字符串。
ask GCC(在Linux / Debian / Sid / x86-64上使用GCC7.2)发出汇编程序更简单。所以我编写了你的程序bflash.c
gcc -fverbose-asm -O0 -S bflash.c -o bflash-O0.S
没有优化就可以得到它
gcc -fverbose-asm -O1 -S bflash.c -o bflash-O1.S
获得-O1
优化。随意用各种other optimization flags重复实验。
即使没有优化,bflash-O0.S
包含:
.section .rodata
.LC0:
.string "Hello World2
"
.LC1:
.string "Hello World3
"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
# bflash.c:5: printf("Hello World2
");
leaq .LC0(%rip), %rdi #,
call puts@PLT #
# bflash.c:6: printf("Hello World3
");
leaq .LC1(%rip), %rdi #,
movl $0, %eax #,
call printf@PLT #
# bflash.c:8: return 0;
movl $0, %eax #, _4
# bflash.c:9: }
popq %rbp #
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
如你所见,第一个printf
已被优化为puts
;这是C11标准n1570(as-if rule)允许的。顺便说一句,bflash-01.S
包含类似的代码。请注意,C11标准已经考虑了当前的优化实践(标准化委员会的许多成员都是编译器实现者)。
BTW Clang 5,作为clang-5.0 -O1 -fverbose-asm -S bflash.c -o bflash-01clang.s
调用,执行相同类型的优化。
我怎样才能避免这种“优化”(!?)
关注Daniel H's answer(你可以编译with -ffreestanding
,但我不建议这样做)。
或者避免使用printf
中的<stdio.h>
并实现自己的慢速打印功能。如果您实现自己的打印功能,请以不同的名称命名(因为printf
是在C11标准中定义的),也许(如果需要的话)编写您自己的GCC plugin以便按照您的方式进行优化(并且该插件最好是一些免费软件is GPL compatible ,阅读GCC runtime library exception)。
C语言规范(研究n1570)定义了semantics,即编译程序的行为。它不需要任何特定的字节序列出现在可执行文件中(标准中甚至可能没有提到)。如果你需要这样的属性,找到一种不同的编程语言,并放弃所有重要的optimizations GCC正在努力为你做。优化正在制作writing a C compiler difficult(如果你想要一个非优化的编译器,使用GCC以外的其他东西,但接受在性能方面可能损失三倍或更多,w.r.t。使用gcc -O2
编译的代码)。
以上是关于如何阻止GCC从obj文件中的字符串文字中删除尾随换行符?的主要内容,如果未能解决你的问题,请参考以下文章