fel*_*021 14 linux gcc strip compiler-optimization
我知道有一个选项"-Os"来"优化尺寸",但它几乎没有影响,甚至在某些场合增加尺寸:(
strip(或"-s"选项)删除调试符号表,工作正常; 但它只能减少尺寸的小比例.
还有其他方法可以继续吗?
Dam*_*mon 15
除了明显的(-Os -s)之外,将函数对齐到不会崩溃的最小可能值(我不知道ARM对齐要求)可能会挤出每个函数的几个字节.
-Os 应该已经禁用了对齐功能,但是这可能仍然默认为4或8之类的值.如果ARM可以将例如1对齐,则可能会节省一些字节.
-ffast-math(或磨损性较小-fno-math-errno)不会设置errno并避免一些检查,这会减少代码大小.如果像大多数人一样,你还没有读过errno,那就是一个选择.
正确使用__restrict(或restrict)并const删除冗余负载,使代码更快更小(更正确).正确标记纯函数,这样可以调用函数调用.
启用LTO可能会有帮助,如果不可用,(编译所有的源文件转换成二进制一气呵成gcc foo.c bar.c baz.c -o program,而不是编译foo.c,bar.c和baz.c第一个目标文件,然后连接)将有类似的效果.它使得优化器一次可见一切,可能使其更好地工作.
-fdelete-null-pointer-checks可能是一个选项(请注意,这通常是使用任何"O"启用,但不是嵌入式目标).
将静态全局变量(希望没有那么多,但仍然存在)放入结构体中可以消除很多开销它们的开销.我在编写第一个OpenGL加载器时学到了这一点.在struct中使用所有函数指针并初始化struct会= {}生成一次调用memset,而初始化指针时,"normal way"会生成一百KB的代码,只是为了将每一个单独设置为零.
避免使用像devil那样的非平凡构造函数静态局部变量(POD类型没问题).Gcc将初始化非平凡构造函数静态本地线程安全,除非你编译-fno-threadsafe-statics,在很多额外代码中链接(即使你根本不使用线程).
使用libowfat而不是普通的crt可以大大减少二进制文件的大小.
您也可以使用 -nostartfiles和/或-nodefaultlibs两者的组合-nostdlib.如果您不想要标准的启动文件,则必须编写自己的_start函数.另见 ompf上的这个帖子:
(引用佩林)
# man syscalls
# cat phat.cc
extern "C" void _start() {
asm("int $0x80" :: "a"(1), "b"(42));
}
# g++ -fno-exceptions -Os -c phat.cc
# objdump -d phat.o
phat.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_start>:
0: 53 push %rbx
1: b8 01 00 00 00 mov $0x1,%eax
6: bb 2a 00 00 00 mov $0x2a,%ebx
b: cd 80 int $0x80
d: 5b pop %rbx
e: c3 retq
# ld -nostdlib -nostartfiles phat.o -o phat
# sstrip phat
# ls -l phat
-rwxr-xr-x 1 tbp src 294 2007-04-11 22:47 phat
# ./phat; echo $?
42
Run Code Online (Sandbox Code Playgroud)
摘要:上面的代码段产生了一个294字节的二进制文件,每个字节为8位.
小智 7
使用条(1) 时,您需要确保使用所有相关选项。由于某种原因,--strip-all并不总是剥夺一切。删除不必要的部分可能会有所帮助。
但最终,减少二进制文件大小的最佳方法是从程序中删除代码和静态数据。让它做得更少,或者选择导致更少指令的编程结构。例如,您可以在运行时构建数据结构,或者按需从文件加载它们,而不是静态初始化的数组。
| 归档时间: |
|
| 查看次数: |
14509 次 |
| 最近记录: |