Kromě zřejmého (-Os -s
), zarovnání funkcí na nejmenší možnou hodnotu, která nebude padat (neznám požadavky na zarovnání ARM), může vytlačit několik bajtů na funkci.
-Os
měl by již deaktivuje funkce zarovnání, ale stále může být výchozí hodnota jako 4 nebo 8. Pokud zarovnáváte např. na 1 je možné s ARM, což může ušetřit nějaké bajty.
-ffast-math
(nebo méně abrazivní -fno-math-errno
) nenastaví errno a vyhne se některým kontrolám, což snižuje velikost kódu. Pokud stejně jako většina lidí nečtete errno, je to možnost.
Správně pomocí __restrict
(nebo restrict
) a const
odstraňuje nadbytečná zatížení, čímž je kód rychlejší a menší (a správnější). Správné označení čistých funkcí jako takových eliminuje volání funkcí.
Povolení LTO může pomoci, a pokud to není k dispozici, zkompilujte všechny zdrojové soubory do binárního souboru najednou (gcc foo.c bar.c baz.c -o program
místo kompilace foo.c
, bar.c
a baz.c
nejprve na objektové soubory a poté propojení) bude mít podobný účinek. Optimalizátoru zviditelní vše najednou, což mu možná umožní lépe pracovat.
-fdelete-null-pointer-checks
může být možnost (všimněte si, že toto je normálně povoleno s libovolným "O", ale ne na vložené cíle).
Vložení statických globálů (doufejme, že jich nemáte tolik, ale přesto) do struktury může eliminovat velkou režii jejich inicializaci. Naučil jsem se to, když jsem psal svůj první zavaděč OpenGL. Mít všechny ukazatele funkcí ve struktuře a inicializovat strukturu pomocí = {}
vygeneruje jedno volání memset
, zatímco inicializace ukazatelů "normálním způsobem" vygeneruje sto kilobajtů kódu, aby bylo možné každý jednotlivě nastavit na nulu.
Vyhněte se netriviálnímu statickému místnímu konstruktoru proměnné jako čert kříže (typy POD nejsou žádný problém). Gcc bude inicializovat netriviální konstruktor statického místního vlákna bezpečného pro vlákna, pokud nezkompilujete s -fno-threadsafe-statics
, která hodně odkazuje kódu navíc (i když vlákna vůbec nepoužíváte).
Použití něčeho jako libowfat místo normálního crt může skvěle zmenšete binární velikost.
Pokud chcete ze svých binárních souborů vymáčknout každou poslední kapku prostoru, pravděpodobně se budete muset naučit sestavovat. Velmi zajímavé (a zábavné) intro najdete na tomto odkazu:
Výukový program Whirlwind o vytváření skutečně Teensy ELF spustitelných souborů pro Linux
Můžete také použít -nostartfiles
a/nebo -nodefaultlibs
nebo kombinaci obou -nostdlib
. V případě, že nechcete standardní spouštěcí soubor, musíte napsat vlastní funkci _start. Viz také toto vlákno (archivované) na oompf:
(cituji Perrina)
# 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
Shrnutí:Výše uvedený úryvek poskytl binární soubor 294 bajtů , každý bajt 8 bitů.
Za předpokladu, že je povolen i jiný nástroj;-)
Pak zvažte UPX:Ultimate Packer for Binaries, který používá runtime dekompresi.
Šťastné kódování.