5.1. Přidělování na zásobníku
  Nejjednodušší metodou přidělování paměti je přidělování z jediného souvislého bloku
  paměti, organizovaného jako zásobník. Pro přidělení potřebujeme mít k dispozici
  pouze adresu začátku a konce volné paměti. Každému požadavku na přidělení paměti
  je přiřazena aktuální adresa začátku volné paměti a tato adresa je pak zvýšena 
  o velikost požadavku, přičemž se hlídá překročení limitu volné paměti. Uvolňování
  paměti je pak implementováno jako prázdná operace, případně je možné bloky paměti 
  uvolňovat vždy v opačném pořadí než v jakém byly přiděleny. Při uvolňování paměti
  je ukazatel začátku volné paměti opět vrácen zpět o velikost uvolňovaného bloku.
  
|  | Příklad 5.1. Přidělování paměti na zásobníku | 
|  | Následující příklad ukazuje implementaci přidělování paměti z jediného souvislého
  bloku, přičemž operace uvolňování je implementována jako prázdná: 
  class SimpleAllocator {
     // Vytvoří objekt typu SimpleAllocator, přidělující volnou paměť z bloku
     // na adrese memAddr o velikosti memSize
     public SimpleAllocator(char* memAddr, unsigned memSize)
     {
     	m_addr = memAddr;
	m_size = memSize;
     }
     // Přidělí blok paměti o velikosti size a vrátí jeho adresu.
     // Není-li požadovaný prostor k dispozici, aktivuje výjimku NoMemoryException
     public char* alloc(unsigned size)
     {
        if( size > m_size )
	   throw new NoMemoryException();
	char* addr = m_addr;
	m_addr += size;
	return addr;
     }
     // Uvolnění bloku paměti je prázdná operace.
     public void free(char* addr, unsigned size) {}
     
     // Aktuální začátek volné paměti
     protected char*    m_addr;
     // Aktuální velikost volné paměti
     protected unsigned m_size;
  }
   | 
|  | 
  Upravte implementaci funkce free tak, aby umožnila vrácení naposledy
  přiděleného bloku paměti. Zamyslete se nad tím, jak by se dala kontrolovat podmínka, že 
  se bloky mohou uvolňovat pouze v obráceném pořadí jejich přidělování.
   | 
  Metoda přidělování ze souvislého bloku paměti je velmi rychlá, a proto se často používá 
  například ve funkci subalokátoru pro přidělování paměti v rámci bloku 
  získaném jinou metodou. Můžeme se s ní také setkat v programovacích jazycích jako je C, 
  C++ nebo Pascal při přidělování paměti pro aktivační záznamy funkcí (obsahující lokální 
  proměnné, návratovou adresu a předávané parametry volání). Právě zde je totiž zajištěno to, 
  že se přidělené bloky uvolňují v obráceném pořadí, a to vždy při návratu z volání funkce.
  
  Jednou z modifikací této metody je zavedení operací mark a
  release. Operace mark uloží aktuální
  hodnotu ukazatele začátku volné paměti do proměnné a operace release
  tento ukazatel z proměnné opět obnoví. Tímto způsobem lze zajistit uvolnění veškeré
  přidělené paměti od okamžiku, kdy byla provedena odpovídající operace mark.
  
|  | Příklad 5.2. Přidělování paměti s metodami mark a release | 
|  | Výše uvedenou třídu SimpleAllocator můžeme rozšířit o operace
  mark a release takto: 
  class StackAllocator: public SimpleAllocator
  {
     // Vytvoří objekt typu StackAllocator, přidělující volnou paměť z bloku
     // na adrese memAddr o velikosti memSize
     public StackAllocator(char* memAddr, unsigned memSize): SimpleAllocator(memAddr, memSize) {}
     // Poznamená aktuální pozici
     public void mark(char* &tr)
     {
        ptr = m_addr;
     }
     // Obnoví poznamenanou pozici
     public void release(char* ptr)
     {
        m_addr = ptr;
     }
  }	
   | 
|  | 
 | 
|  | Úkol k zamyšlení | 
|  | Jakým způsobem by bylo možné kontrolovat, zda byla adresa předaná funkci release
  získána voláním funkce mark? Jaké další situace by mohly vést k nesprávné funkci
  takto implementovaného přidělování paměti? | 
|  | 
 |