Zaawansowane CPP/Ćwiczenia 14: Zarządzanie pamięcią: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Mirek (dyskusja | edycje)
Nie podano opisu zmian
Nie podano opisu zmian
 
(Nie pokazano 14 wersji utworzonych przez jednego użytkownika)
Linia 23: Linia 23:


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
Przykładowe rozwiązanie znajduje się w pliku  [http://osilek.mimuw.edu.pl/images/6/68/Linked_pool.h linked_pool.h].
Przykładowe rozwiązanie znajduje się w pliku  [[media:Linked_pool.h | linked_pool.h]].
</div></div>
</div></div>


Linia 69: Linia 69:
     };
     };


Całość kodu można zobaczyć w pliku [http://osilek.mimuw.edu.pl/images/6/68/Linked_pool.h linked_new.h].   
Całość kodu można zobaczyć w pliku [[media:Linked_new.h | linked_new.h]].   


Z klasy <tt>linked_pool_new</tt> korzystamy dziedzicząc z niej:
Z klasy <tt>linked_pool_new</tt> korzystamy dziedzicząc z niej:
Linia 88: Linia 88:
kontenerów?
kontenerów?
}}
}}
{{cwiczenie|5||
W oparciu o <code><nowiki>linked_pool</nowiki></code> napisz własny alokator pamięci.
Do jakich pojemników będzie można go stosować?.
}}


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
Przykładowy alokator oparty o funkcję <tt>malloc</tt> jest
zaimplementowany w pliku [[media:Mallocator.h | mallocator.h]].  Funkcje <tt>allocate</tt> i <tt>deallocate</tt> są tak
zdefiniowane, że wypisują informacje o rozmiarze i ilości alokowanych
elementów:


'''Rozwiązanie 4 '''
Przykładowy alokator oparty o funkcje {malloc} jest
zaimplementowany w {mod12/exercices/mallocator.h}<tt>mallocator.h</tt>.  Funkcje {allocate} i {deallocate} są tak
zdefiniowane że wypisują informacje o rozmiarze i ilości alokowanych
elementów:
   pointer allocate(size_type n, const_pointer <nowiki> =</nowiki>    0) {
   pointer allocate(size_type n, const_pointer <nowiki> =</nowiki>    0) {
     void* p <nowiki> =</nowiki>  malloc(n * sizeof(T));
     void* p <nowiki> =</nowiki>  malloc(n * sizeof(T));
Linia 118: Linia 101:
       throw std::bad_alloc();
       throw std::bad_alloc();
     return static_cast<pointer>(p);
     return static_cast<pointer>(p);
   }
   }<br>
 
   void deallocate(pointer p, size_type n) {  
   void deallocate(pointer p, size_type n) {  
   std::cerr<<"d "<<n<<" "<<sizeof(T)<<" "<<p<<std::endl;
   std::cerr<<"d "<<n<<" "<<sizeof(T)<<" "<<p<<std::endl;
   free(p); }
   free(p); }
 
Wykonując np. instrukcje:
Wykonując np. instrukcje:
   
   
Linia 132: Linia 114:
   std::cerr<<"list"<<std::endl;  
   std::cerr<<"list"<<std::endl;  
   std::list<int,malloc_allocator<int> > l(4);
   std::list<int,malloc_allocator<int> > l(4);
łatwo się przekonać że np. {vector} i {deque} alokują pamięć dla
wielu elementów na raz natomiast lista alokuje pamięć po jednym
elemencie.


'''Rozwiązanie 5 '''
łatwo się przekonać, że np. <tt>vector</tt> i <tt>deque</tt> alokują pamięć dla
wielu elementów na raz, natomiast lista alokuje pamięć po jednym elemencie.
</div></div>
 
{{cwiczenie|5||


Z powyższego ćwieczenia widać, że prosty alokator przydzielający
W oparciu o <code><nowiki>linked_pool</nowiki></code> napisz własny alokator pamięci.
Do jakich pojemników będzie można go stosować?.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
Z powyższego ćwiczenia widać, że prosty alokator przydzielający
pamięć na pojedyncze elementy tego samego rozmiaru, będzie mogł być
pamięć na pojedyncze elementy tego samego rozmiaru, będzie mogł być
użyty tylko z tymi pojemnikami które alokują pamięć pojedenczo np. z
użyty tylko z tymi pojemnikami, które alokują pamięć pojedynczo, np. z
listą. Ale właśnie takie pojemniki mogą najbardziej skorzystać z
listą. Ale właśnie takie pojemniki mogą najbardziej skorzystać z
przyspieszenia swojego działania dzięki sprawniejszej alokacji i
przyspieszenia swojego działania dzięki sprawniejszej alokacji i
dealokacji pamięci.
dealokacji pamięci.


Implementując alokator oparty o {linked_pool} znów musimy uważać na
Implementując alokator oparty o <tt>linked_pool</tt> znów musimy uważać na sposób przydziału pamięci dla puli. Ponieważ musimy zapewnić równoważność iteratorów, każda lista musi alokować pamięć z tej samej puli. Pula będzie więc składową statyczną alokatora. Z powodu mechanizmu <tt>rebind</tt> nie możemy jednak teraz przydzialać pamięci dla puli dynamicznie, tak jak to robiliśmy w <tt>linked_pool_new</tt>. Dlatego rozmiar puli będzie podawany jako drugi argument szablonu alokatora:
sposób przydziału pamięci dla puli. Ponieważ musimy zapewnić
 
równoważność iteratorów każda lista musi alokować pamięć z tej samej
  template <class T,size_t N> class      pool_allocator {
puli. Pula będzie więc składową statyczną alokatora. Z powodu
  private:
mechanizmu {rebind} nie możemy jednak teraz przydzialać pamięci dla
static  linked_pool<T> _pool;   
puli dynamicznie, tak jak to robiliśmy w {linked_pool_new}. Dlatego
 
rozmiar puli będzie podawany jako drugi argument szablonu alokatora:
   
template <class T,size_t N> class      pool_allocator {
private:
static  linked_pool<T> _pool;   
Inicjalizacja puli wygląda następująco:
Inicjalizacja puli wygląda następująco:
   
 
template<class T,size_t N>  linked_pool<T> pool_allocator<T,N>::_pool(N);   
  template<class T,size_t N>  linked_pool<T> pool_allocator<T,N>::_pool(N);   
 
(składowe statczne inicjalizowane są poza klasą).  
(składowe statyczne inicjalizowane są poza klasą). Wyrażenie <tt>rebind</tt> ma teraz postać:
Wyrażenie {rebind} ma teraz postać:
   
   
  template <class U>  
  template <class U>  
  struct rebind { typedef pool_allocator<U,N> other; };
  struct rebind { typedef pool_allocator<nowiki><U,N></nowiki> other; };
 
Całość kodu jest zamieszczona w pliku  
Całość kodu jest zamieszczona w pliku [[media:Pool_allocator.h | pool_allocator.h]]. Z tak zdefiniowanego alokatora korzysta się następująco:
{mod12/exercices/pool_allocator.h}<tt>poolallocator.h</tt>.
 
Z tak zdefiniowanego alokatora korzysta się następująco:
  std::list<int,pool_allocator<int,10000> > l;
   
</div></div>
  std::list<int,pool_allocator<int,10000> > l;

Aktualna wersja na dzień 10:51, 2 paź 2006

Ćwiczenie 1

Przerób przykłady z wykładu.

Ćwiczenie 2

Napisz własną implementację puli pamięci opartą o listę. Zasobnik powinien być szablonem przyjmującym jako parametr typ obiektów, dla których będzie przydzielał pamięć. Wielkość puli powinna być podawana w konstruktorze. Jeśli zażądamy za dużo pamięci, to powinien zostać rzucony wyjątek std::bad_alloc. Jeśli wyczerpie się pamięć w puli, żądanie przydziału powinno rzucić std::bad_alloc:

template<typename T> linked_pool {
linked_pool(size_t n) throw(std::bad_alloc); void *allocate() throw(std::bad_alloc); /*przydziela pamięc na jeden obiekt T*/ void deallocate(void *p) throw ();
release() throw (); /*zwalnia całą pamięć z puli*/ ~linked_pool() throw() ; }
Rozwiązanie

Ćwiczenie 3

W oparciu o linked_pool zaimplementuj klasę z własnymi operatorami new i delete. Zaimplementuj klasę tak, aby można było z niej dziedziczyć i w ten sposób łatwo implementować new i delete w dowolnej klasie.

Wskazówka
Rozwiązanie

Ćwiczenie 4

Przerób nieznacznie alokator podany na wykładzie, tak aby jego funkcje wypisywały informacje o tym co robią. Użyj go z różnymi typami pojemników. Co możesz powiedzieć o sposobie przydziału pamięci dla różnych kontenerów?

Rozwiązanie

Ćwiczenie 5

W oparciu o linked_pool napisz własny alokator pamięci. Do jakich pojemników będzie można go stosować?.

Rozwiązanie