Dynamická alokace zásobníku
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
How to program in "C"
1] Use lots of global variables.
2] Give them cryptic names such as: X27, a_gcl, or Horace.
3] Put everything in one large .h file.
4] Implement the entire project at once.
5] Use macros and #defines to emulate Pascal.
6] Assume the compiler takes care of all the little details you
didn't quite understand.
"It's 5:50 a.m., Do you know where your stack pointer is?"
V klasickém C je zásobník učen výhradně pro automatické
proměnné, které mají předem danou velikost. Vlastní pojetí zásobníku
ale nijak nebrání ani alokacím proměnné délky. GNU C (a některé
další překladače C) rozšiřuje syntax C o možnost dát polím proměnnou
délku.
I tento přístup je často poněkud těžkopádný a navíc úplně
nepřenositelný na platformy bez GNU C. Užitečné je i další rozšíření
jazyka C - alloca. To je "funkce", která funguje podobně jako
malloc, ale alokuje data na zásobníku. Blok se automaticky uvolní
na konci funkce. Není tedy nutné se starat o volání free. Tato
vlastnost je velmi praktická - i v případě, že funkce spadne,
nebo použije longjmp (případně jej použije nějaká funkce z ní
volaná), paměť se spolehlivě uvolní. Je tedy velmi těžké zapomenout
neuvolněný blok.
Další jednoznačnou výhodou alloca je jeho rychlost a úspornost.
GNU C má alloca implementovanou jako builtin do překladače a alloca
se tedy nepřekládá jako volání funkce. Navíc na zásobníku nemůže
vzniknout fragmentace a tak blok zabírá přesně tolik paměti, kolik
má.
Nevýhody alloca jsou zejména v jeho nepřenositelnosti. Situace
sice není tak špatná - mnoho ne-GNU systémů alloca implementuje.
Manuálová stránka se o přenositelnosti alloca vyjadřuje takto:
There is evidence that the alloca function appeared in 32v, pwb,
pwb.2, 3bsd, and 4bsd. There is a man page for it in BSD 4.3. Linux
uses the GNU version.
Existuje i public-domain implementace alloca jako C funkce.
Mnoho libc na různých platformách funkci už obsahuje a zdrojové kódy
jsou distribuovány například společně s GCC. Tato funkce ale funguje
poněkud jinak. Alokuje bloky na haldě a při každém volání projde
všechny bloky a zjistí, jestli funkce, která blok vytvořila už
zkončila. Proto je při použití alloca vhodné použít někde v hlavní
smyčce alloca(0) a vyvolat tak garbage-collection.
Program v UNIXu běžně nemá prostředky na zjištění volného místa
na zásobníku. Proto v případě, že je plná paměť, program spadne
podobně jako při nekonečné rekursi. Narozdíl od mallocu, alloca tedy
nevrátí NULL (přesto, že to manuálová stránka o něm tvrdí). Tak se
chová pouze jeho knihovní implementace. V DJGPP je situace navíc
komplikována tím, že zásobník má omezenou velikost a standardně je
poměrně malý a proto je nutné si dát pozor na přetečení.
výheň