Search
— Jan Faigl 2025/09/19 19:45
— Jan Faigl 2023/11/16 15:32 / Aktualizace: Doplnění volání fill_numbers() a print() v save_struct.c.
fill_numbers()
print()
save_struct.c
— Jan Faigl 2023/11/19 20:00 Umístění errno.h
Chybové kódy standardní knihovny C jsou definovány v souboru errno.h, umístění souboru s definicí chyb je však na různých systémch různé. V unixovových systém se jedná zpravidla o /usr/include/errno.h případně /usr/include/sys/errno.h, popis jednotlivých konstant a hodnot lze také najít např. v man errno. V distribucích Linuxu je situace trošku složitější, neboť umístění záleží na konkrétní distribuci, např. lP5oGIqdWEU
errno.h
/usr/include/errno.h
/usr/include/sys/errno.h
man errno
Konkrétní soubor můžeme najít například příkazem
grep -R 17 /usr/include/**/errno*.h /usr/include/asm-generic/errno-base.h:#define EEXIST 17 /* File exists */ /usr/include/asm-generic/errno.h:#define EUCLEAN 117 /* Structure needs cleaning *
jehož výstup nám napoví, že na tomto konkrétním Linuxu jsou rozděleny chybové kódy do souborů errno-base.h (obsahující základní kódy) a errno.h obsahující rozšířené kódy, tj. kódy s vyšší hodnotou.
errno-base.h
Dále je většinou v Linuxu standardní knihovna libc realizována jako GNU libc (glibc ), což přináší některé zajímavé funkce , které na druhou stranu nejsou dostupné na jiných OS, nelinuxového typu, např. OS X.
GNU libc
Q: Je nějaké omezení na hloubku rekurzivního volání?
Ano, při volání funkce se minimálně ukládá na zásobník adresa odkud funkci voláme, aby mohlo dojít k návratu z volání funkce. Dále se při každém volání mohou vytvářet na zásobníku lokální proměnné. Tedy omezení je dáno velikostí zásobníku. Omezení si můžeme vyzkoušet následujícím programem.
#include <stdio.h> void printValue(int v); int main(void) { printValue(1); } void printValue(int v) { printf("value: %i\n", v); printValue(v + 1); }
a spuštěním s omezenou velikostí zásobníku
ulimit -s 1000; ./a.out | tail -n 3 value: 31730 value: 31731 Segmentation fault
a s větší velikostí.
ulimit -s 10000; ./a.out value: 319816 value: 319817 Segmentation fault
V obou případech končí volání chybou. Ve druhém případě došlo k hlubšímu zanoření. Zotavení z chybějícího místa na zásobníku je velmi náročné, narozdíl od dynamické alokace. Výchozí hodnota zásobníku je nastavana na relativně dostačující velikost pro běžné programy. Nicméně v případě rekurzivního řešení je dobré pamatovat, že místo na zásobníku není neomezené. Proto je vždy vhodné rozumět úloze a konkrétním (typickým) vstupům a prostředí. Například na základě velikosti vstupu můžeme odhadnout, potřebnou velikost zásobníku a případně uživatele informovat. Asi nejhorší případ je, když program padá a netušíme proč tomu tak je.