S programem jako
int main()
{
return 0;
}
- a vy staticky propojíte, bude nějaká knihovna ve vašem systému propojena do konečného binárního souboru.
- a vy dynamicky propojíte, bude knihovna načtena, když je spuštěna?
V podstatě je knihovna vždy vyžadována i pro ty nejjednodušší programy, pokud ano, proč? Ptám se, protože jsem si myslel, že kanonický vstupní bod pro cokoli, co chce být vykonáno, je ve skutečnosti _start (o kterém jsem si myslel, že je v knihovně, jmenovitě glibc). Možná nerozumím tomu, co _start skutečně dělá, pokud jde o nastavování věcí, takže by se také hodily jakékoli odkazy.
Přijatá odpověď:
Pokud chcete napsat svůj program ve standardním přenosném C, potřebujete samozřejmě nějaký runtime, který volá main()
funkce na prvním místě.
Ale pokud vás to nezajímá, můžete se obejít bez jakékoli knihovny a systémová volání provádět přímo prostřednictvím inline sestavy. Např. pro x86-64:
$ cat q.c
#include <sys/syscall.h>
void _start(void){
__asm__( "syscall" : : "D"(0), "a"(SYS_exit) );
}
$ cc -O2 -static -nostdlib -nostartfiles -Wall q.c -o q
$ strace ./q
execve("./q", ["./q"], 0x7fffc72d8d20 /* 39 vars */) = 0
exit(0) = ?
+++ exited with 0 +++
Musíte provést alespoň jedno systémové volání, konkrétně _exit(2)
, pokud není pro „nejjednodušší program“ přijatelné ukončení po havárii, v takovém případě postačí i prázdný soubor;-):
$ > foo.c
$ cc -static -nostdlib -nostartfiles -Wall foo.c -o ./foo
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
$ ./foo
Segmentation fault
Myslel jsem, že kanonický vstupní bod pro cokoli, co chce být vykonáno, je ve skutečnosti
_start
není na tom nic kanonického; _start
je výchozí název, který linker použije; můžete jej nasměrovat jinam pomocí -e sym
možnost (-Wl,-e,sym
pomocí gcc
).