31
Programiranje 2 Dinamiˇ cka alokacija memorije dr Nina Radojiˇ ci´ c Matematiˇ cki fakultet Univerzitet u Beogradu [email protected] februar 2019.

Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

  • Upload
    others

  • View
    4

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Programiranje 2

Dinamicka alokacija memorije

dr Nina Radojicic

Matematicki fakultet

Univerzitet u Beogradu

[email protected]

februar 2019.

Page 2: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Sadrzaj

Uvod

Dinamicka alokacija memorije

Funkcije standardne biblioteke jezika C za rad sa dinamickom memorijom

Greske u radu sa dinamickom memorijom

Fragmentisanje memorije

1

Page 3: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Uvod

Page 4: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Dinamicka alokacija memorije

Page 5: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Uvod

Zasto dinamicka alokacija memorije?

Cesto u trenutku pisanja programa nije moguce precizno predvideti

memorijske zahteve programa.

• Memorijski zahtevi zavise od interakcije sa korisnikom.

• Predvidanje gornjeg ogranicenja velicine niza nije uvek

zadovoljavajuce.

2

Page 6: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Dinamicka alokacija memorije

Dinamicka alokacija memorije

omogucava da program u toku svog rada, u fazi izvrsavanja, zahteva

(od operativnog sistema) odredenu kolicinu memorije.

• U trenutku kada programu vise nije potrebna memorija koja je

dinamicki alocirana, program treba da je oslobodi i time vrati

operativnom sistemu na koriscenje.

3

Page 7: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Hip i dinamicki zivotni vek

Memorija dodeljena programu organizovana je u nekoliko delova

koji se nazivaju segmenti:

• segment koda;

• segment podataka;

• stek segment;

• hip segment.

Hip (engl. heap) segment

• Hip segment predstavlja tzv. slobodnu memoriju iz koje se crpi

memorija koja se dinamicki alocira.

• Objekti koji su alocirani u slobodnom memorijskom prostoru nisu

imenovani (pristupa im se preko adresa).

• Dinamicki alocirani objekti imaju dinamicki zivotni vek tj. memorija

se alocira i oslobada iskljucivo na eksplicitni zahtev tokom rada

programa.4

Page 8: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Hip segment

Hip segment

• Obicno pocinje neposredno nakon segmenta podataka, a na

suprotnom kraju memorije od stek segmenta;

• Obicno se podaci na hipu slazu od manjih ka vecim adresama (engl.

upward growing), dok se na steku slazu od vecih ka manjim

adresama (engl. downward growing).

Sta se desava kada se iscrpi memorijski prostor dodeljen programu?

5

Page 9: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Funkcije standardne biblioteke

jezika C za rad sa dinamickom

memorijom

Page 10: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Funkcije standardne biblioteke jezika C za rad sa dinamickom

memorijom

Nekoliko funkcija koje su deklarisane u zaglavlju <stdlib.h>.

• malloc,

• calloc,

• free,

• realloc.

Podsetnik: tip size t

• nenegativni celobrojni tip za cije vrednosti je rezervisano najmanje

dva bajta.

• razlikuje od tipa unsigned int ali su medusobne konverzije

trivijalne.

• moze da se koristi za cuvanje bilo kog indeksa niza.

• tip povratne vrednosti operatora sizeof.

6

Page 11: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Alociranje memorije

Prototip funkcije malloc

void *malloc(size_t n);

• malloc alocira blok memorije (tj. niz uzastopnih bajtova) velicine n

bajtova i vraca adresu alociranog bloka u vidu generickog pokazivaca

(tipa void*).

• Memorija na koju funkcija malloc vrati pokazivac nije

inicijalizovana.

Prototip funkcije calloc

void *calloc(size_t n, size_t size);

• calloc vraca pokazivac na blok memorije velicine n objekata

navedene velicine size.

• Za razliku od malloc, alocirana memorija je inicijalizovana na nulu.

7

Page 12: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Alociranje memorije: malloc & calloc

• Dinamicki objekti alocirani navedenim funkcijama su neimenovani i

bitno su razliciti od promenljivih.

• Dinamicki alociranim blokovima se pristupa na slican nacin kao

nizovima.

malloc & calloc

• Genericke funkcije i koriste se za dinamicku alokaciju memorije za

podatke bilo kog tipa.

• Da bi se dobijenoj memoriji moglo pristupati slicno kao u slucaju

nizova, potrebno je (pozeljno eksplicitno) konvertovati dobijeni

pokazivac tipa void* u neki konkretni pokazivacki tip.

8

Page 13: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Alociranje memorije - provera

Nakon poziva funkcije malloc() ili calloc() obavezno treba proveriti

povratnu vrednost kako bi se utvrdilo da li je alokacija uspela.

int* p = (int*) malloc(n*sizeof(int));

if (p == NULL)

/* pokusati oporavak od greske ili prijaviti gresku */

Ukoliko alokacija ne uspe, pokusaj pristupa memoriji na koju ukazuje

dobijeni pokazivac dovodi do dereferenciranja NULL pokazivaca i greske.

Ako je alokacija uspesna, u nastavku programa se p moze koristiti kao

(staticki alociran) niz celih brojeva.

Napomena

Racunanje izraza n*sizeof(int) moze dovesti do prekoracenja za

veoma velike vrednosti n (savet: upotrebiti calloc).

9

Page 14: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Oslobadanje dinamicki alocirane memorije

Prototip funkcije free

void free(void* p);

• Poziv free(p) oslobada memoriju na koju ukazuje pokazivac p, pri

cemu je neophodno da p pokazuje na blok memorije koji je alociran

pozivom funkcije malloc ili calloc.

• Ne sme se koristiti nesto sto je vec oslobodeno.

• Redosled oslobadanja memorije ne mora da odgovara redosledu

alociranja.

• Ukoliko neki dinamicki alociran blok nije osloboden ranije, on ce biti

osloboden prilikom zavrsetka rada programa.

10

Page 15: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Primer u kojem se unosi i obratno ispisuje niz ciji broj elemenata

nije unapred poznat

#include <stdio.h>

#include <stdlib.h>

int main() {

int n, i, *a;

/* Unos broja elemenata */

scanf("%d", &n);

/* Alocira se memorija */

if ((a = (int*)malloc(n*sizeof(int))) == NULL) {

printf("Greska prilikom alokacije memorije\n");

return 1;

}

/* Unos elemenata */

for (i = 0; i < n; i++) scanf("%d",&a[i]);

/* Ispis elemenata u obratnom poretku */

for (i = n-1; i >= 0; i--) printf("%d ",a[i]);

/* Oslobadjanje memorije */

free(a);

return 0;

}

11

Page 16: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Promena velicine alociranog bloka memorije

Prototip funkcije free

void *realloc(void *memblock, size_t size);

• Parametar memblock je pokazivac na prethodno alocirani blok

memorije, a parametar size je nova velicina u bajtovima.

• Postupak:

• ukoliko iza postojeceg bloka postoji dovoljno slobodnog prostora, taj

prostor se jednostavno koristi za prosirivanje.

• ukoliko iza postojeceg bloka ne postoji dovoljno slobodnog prostora,

onda se u memoriji trazi drugo mesto dovoljno da prihvati prosireni

blok i, ako se nade, sadrzaj postojeceg bloka se kopira na to novo

mesto i zatim se stari blok memorije oslobada.

• Ova operacija moze biti vremenski zahtevna.

12

Page 17: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Program koji ucitava cele brojeve i smesta ih u memoriju, sve

dok se ne unese -1 za kraj

#include <stdio.h>

#include <stdlib.h>

#define KORAK 100

int main() {

int* a = NULL; /* Niz je u pocetku prazan */

int duzina = 0; /* broj popunjenih elemenata niza */

int alocirano = 0; /* koliko elemenata moze biti smesteno */

int i;

do {

printf("Unesi ceo broj (-1 za kraj): ");

scanf("%d", &i);

if (duzina == alocirano) { /* Ako nema vise slobodnih mesta, vrsi se prosirivanje */

alocirano += KORAK;

a = realloc(a, alocirano*sizeof(int));

if (a == NULL) return 1;

}

a[duzina++] = i;

} while (i != -1);

/* Ispis elemenata */

printf("Uneto je %d brojeva. Alocirano je %d bajtova\n", duzina, alocirano*sizeof(int));

printf("Brojevi su : ");

for (i = 0; i<duzina; i++) printf("%d ", a[i]);

free(a);/* Oslobadjanje memorije */

return 0;

}

13

Page 18: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Program koji ucitava cele brojeve i smesta ih u memoriju, sve

dok se ne unese -1 za kraj

Bez upotrebe funkcije realloc centralni blok navedene funkcije main bi

mogao da izgleda ovako:

if (duzina == alocirano) {

/* Kreira se novi niz */

int* new_a;

alocirano += KORAK;

new_a = malloc(alocirano*sizeof(int));

if (new_a == NULL) return 1;

/* Kopira se sadrzaj starog niza u novi */

for (i = 0; i < duzina; i++) new_a[i] = a[i];

/* Oslobadja se stari niz */

free(a);

/* a ukazuje na novi niz */

a = new_a;

}

U ovoj implementaciji, prilikom svake realokacije vrsi se premestanje

sadrzaja memorije, tako da je ona neefikasnija od verzije sa realloc.

14

Page 19: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Program koji ucitava cele brojeve i smesta ih u memoriju, sve

dok se ne unese -1 za kraj

U prvo navedenom primeru koristi se konstrukcija:

a = realloc(a, alocirano*sizeof(int));

U nekim slucajevima ova konstrukcija moze da bude neadekvatna ili opasna.

Naime, ukoliko zahtev za prosirenje memorijskog bloka ne uspe, vraca se

vrednost NULL, upisuje u promenljivu a i time se gubi jedina veza sa

prethodno alociranim blokom (i on, na primer, ne moze ubuduce da bude

osloboden).

15

Page 20: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Greske u radu sa dinamickom

memorijom

Page 21: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Greske u radu sa dinamickom memorijom

• Curenje memorije

• Pristup oslobodenoj memoriji

• Oslobadanje istog bloka vise puta

• Oslobadanje neispravnog pokazivaca

• Prekoracenja i potkoracenja bafera

16

Page 22: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Greske u radu sa dinamickom memorijom

Curenje memorije (engl. memory leak):

Situacija kada se u tekucem stanju programa izgubi informacija o

lokaciji dinamicki alociranog, a neoslobodenog bloka memorije.

char* p;

p = (char*) malloc(1000);

/* Deo koda u kome nema poziva free(p) */

p = (char*) malloc(5000);

Program vise nema mogucnost da oslobodi taj blok memorije i on biva

”zauvek“ (tj. do kraja izvrsavanja programa) izgubljen.

17

Page 23: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Curenje memorije

Curenja memorije koja se dogadaju u okviru neke petlje posebno

opasna - tada se gubi malo po malo memorije.

Moguce je da u nekom trenutku program iscrpi svu raspolozivu memoriju i

onda ce njegovo izvrsavanje biti prekinuto od strane operativnog sistema.

Cak i da se to ne desi, moguce je da se iscrpi raspolozivi prostor u

glavnoj memoriji i da se, zbog toga, sadrzaj glavne memorije prebacuje

na disk i obratno (tzv. swapping) - to ekstremno usporava rad programa.

Vecina programa za otkrivanje gresaka (debagera) detektuje da u

programu postoji curenje memorije (ostaje locirati gresku u kodu).

Postoje specijalizovani programi profajleri za curenje memorije (engl.

memory leaks profilers) koji olaksavaju otkrivanje uzroka curenja

memorije.

18

Page 24: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Greske u radu sa dinamickom memorijom

Pristup oslobodenoj memoriji:

Nakon poziva free(p), memorija na koju pokazuje pokazivac p se

oslobada, ali se ne menja sadrzaj pokazivaca p.

Savet: Nakon poziva free(p), odmah: p=NULL; pa ce pokusaj pristupa

oslobodenoj memoriji biti prepoznat - OS ce zaustaviti izvrsavanje

programa sa porukom o gresci (najcesce segmentation fault).

Oslobadanje istog bloka vise puta:

Nakon poziva free(p), svaki naredni poziv free(p) za istu vrednost

pokazivaca p prouzrokuje nedefinisano ponasanje programa. Takozvana

visestruka oslobadanja mogu da dovedu do pada programa.

19

Page 25: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Greske u radu sa dinamickom memorijom

Oslobadanje neispravnog pokazivaca:

Prilikom poziva free(p), p mora biti adresa vracena od strane funkcija

malloc, calloc ili realloc.

Prosledivanje pokazivaca na lokaciju koja pripada alociranom bloku (a

nije njegov pocetak) uzrokuje probleme, kao na primer: free(p + 10).

Prekoracenja i potkoracenja bafera:

Kao i u slucaju staticki alociranih nizova, pristup elementima van

granice moze da prouzrokuje ozbiljne probleme u radu programa.

Upis van granica bloka najcesce je opasniji od citanja.

20

Page 26: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Fragmentisanje memorije

Page 27: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Fragmentisanje memorije

Cak u slucaju ispravne aplikacije u kojima ne postoji curenje memorije (a

koje cesto vrse dinamicku alokaciju i dealokaciju memorije) tokom dugog

rada pokazuju degradaciju u performansama i na kraju prekidaju svoj rad

na nepredvideni nacin - sto moze biti zbog fragmentisanja memorije.

Fragmentisanje memorije

U slucaju fragmentisane memorije, u memoriji se cesto nalazi dosta

slobodnog prostora, ali on je rascepkan na male, nepovezane parcice.

Primer (0 oznacava slobodni bajt i 1 oznacava zauzeti bajt)

Memorija trenutno ima sadrzaj 100101011000011101010110 Postoji

ukupno 12 slobodnih bajtova, pokusaj alokacije 5 bajtova ne moze da

uspe.

Ako memorija ima sadrzaj 111111111111111100000000 Ima samo 8

slobodnih bajtova, ali jeste u stanju da izvrsi alokaciju 5 trazenih

bajtova.

21

Page 28: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Pristupi za izbegavanje fragmentisanja memorije

Memoriju na hipu dodeljenu programu nije moguce automatski

reorganizovati u fazi izvrsavanja, jer nije moguce u toj fazi azurirati sve

pokazivace koji ukazuju na objekte na hipu.

Pristupi za izbegavanje fragmentisanja memorije

• Ukoliko je moguce, pozeljno je izbegavati dinamicku alokaciju

memorije.

• Ukoliko se ipak koristi dinamicka alokacija memorije, pozeljno je

memoriju alocirati u vecim blokovima i umesto alokacije jednog

objekta alocirati prostor za nekoliko njih odjednom.

• Postoje tehnike efikasnijeg rukovanja memorijom (na primer, memory

pooling ), u kojima se programer manje oslanja na sistemsko resenje,

a vise na svoje resenje koje je prilagodeno specificnim potrebama.

22

Page 29: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Zakljucak

Dinamicka alokacija memorije

• Omogucava da program u toku svog rada, u fazi izvrsavanja, zahteva

(od operativnog sistema) odredenu (adekvatnu) kolicinu memorije.

• Korisna zbog svoje fleksibilnosti, ali treba biti obazriv...

23

Page 30: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Literatura

Knjige

Filip Maric, Predrag Janicic: Programiranje 1

Gordana Pavlovic-Lazetic: Programiranje 1

Brajan Kernigan, Denis Rici: Programski jezik C

Filip Maric, Predrag Janicic: Programiranje 2

24

Page 31: Programiranje 2 - Dinamicka alokacija memorijepoincare.matf.bg.ac.rs/~nina/P2/dinamickaAlokacija.pdf · 2019-02-26 · Ukoliko alokacija ne uspe, poku saj pristupa memoriji na koju

Pitanja?

24