You are on page 1of 65

Curs: alocarea dinamică

laura.vasilescu@cs.pub.ro

Reminder Stivă (stack) vs Heap

Reminder Stivă (stack) vs Heap

Reminder Stivă (stack) vs Heap • Variabile locale .

Reminder Stivă (stack) vs Heap • Variabile locale • Variabile alocate dinamic .

Reminder Stivă (stack) vs Heap • Variabile locale • Variabile alocate dinamic • Variabile globale .

Alocarea memoriei pe stivă .recapitulare - .

Exemplu didactic: procesor pe 4 biți 24-1 0 .

Exemplu didactic: procesor pe 4 biți 24-1 . o celulă din memorie are și ea tot 4 biți .Presupunem că tipul de date halfbyte are și el 4 biți și e singurul care există 0 .Presupunem că. în cazul acesta.

Exemplu didactic: procesor pe 4 biți 0xF 14 0xE 8 Alocarea 0xD 14 variabilelor 0xC 4 0xB 11 0xA 5 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 .

Alocarea 0xE 8 0xD 14 variabilelor 0xC 4 0xB 11 0xA 5 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8.

c = 5. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. Alocarea 0xE c = 5 0xD 14 variabilelor 0xC 4 0xB 11 0xA 5 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 .

Alocarea 0xE c = 5 halfbyte *b. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. *d. 4 0xB 11 Ce valori au variabilele b și d? 0xA 5 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . c = 5. 14 variabilelor 0xC d. 0xD b.

Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. Alocarea 0xE c = 5 halfbyte *b. *d. c = 5. 0xD b = 14 variabilelor 0xC d = 4 0xB 11 0xA 5 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 .

0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = ? 0xA 5 print(d) = ? 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. Alocarea 0xE c = 5 halfbyte *b. c = 5. *d.

Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. 0x4 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . *d. Alocarea 0xE c = 5 halfbyte *b. 0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = 14 . 0xE 0xA 5 print(d) = 4. c = 5.

c = 5. 0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = 0xE 0xA 5 print(d) = 0x4 0x9 0 0x8 3 print(*b) = ? 0x7 13 0x6 5 print(*d) = ? 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Alocarea 0xE c = 5 halfbyte *b. *d. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8.

c = 5. *d. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. Alocarea 0xE c = 5 halfbyte *b. 0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = 0xE 0xA 5 print(d) = 0x4 0x9 0 0x8 3 print(*b) = valoarea de la 14 = *0xE = 5 0x7 13 0x6 5 print(*d) = ? 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 .

0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = 0xE 0xA 5 print(d) = 0x4 0x9 0 0x8 3 print(*b) = valoarea de la 14 = *0xE = 5 0x7 13 0x6 5 print(*d) = valoarea de la 4 = *0x4 => 0x5 12 Segmentation Fault 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Alocarea 0xE c = 5 halfbyte *b. c = 5. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. *d.

*d. ?? 0x2 7 *d = 10. 0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = 0xE 0xA 5 print(d) = 0x4 0x9 0 0x8 3 print(*b) = valoarea de la 14 = *0xE = 5 0x7 13 0x6 5 print(*d) = valoarea de la 4 = *0x4 => 0x5 12 Segmentation Fault 0x4 0 0x3 4 *b = 10. ?? 0x1 1 0x0 2 . c = 5. Modificarea 0xE c = 5 halfbyte *b. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8.

c = 5. Segmentation Fault 0x1 1 0x0 2 . 0xD b = 14 variabilelor 0xC d = 4 0xB 11 print(b) = 0xE 0xA 5 print(d) = 0x4 0x9 0 0x8 3 print(*b) = valoarea de la 14 = *0xE = 5 0x7 13 0x6 5 print(*d) = valoarea de la 4 = *0x4 => 0x5 12 Segmentation Fault 0x4 0 0x3 4 *b = 10. se modifică valoarea de la 0xE 0x2 7 *d = 10. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. *d. Modificarea 0xE c = 10 halfbyte *b.

adică 15 0xA 5 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0xD b = 15 variabilelor 0xC d = 4 0xB 11 b = &a. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. Modificarea 0xE c = 10 halfbyte *b. *d. adică b devine 0xF. c = 5.

0xA 5 d = &c. Modificarea 0xE c = 10 halfbyte *b. Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. 0xD b = 15 variabilelor 0xC d = 14 0xB 11 b = &a. adică d devine 0xE. *d. adică 14 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . c = 5.

Exemplu didactic: procesor pe 4 biți 0xF a = 8 halfbyte a = 8. 0xA 5 d = &c. adică d devine 0xE. *d. c = 5. 0xD b = 15 variabilelor 0xC d = 14 0xB 11 b = &a. adică 14 0x9 0 0x8 3 *b = 1. Modificarea 0xE c = 10 halfbyte *b. deci a devine 1 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 .

c = 5. 0xD b = 15 variabilelor 0xC d = 14 0xB 11 b = &a. adică d devine 0xE. 0xA 5 d = &c. adică 14 0x9 0 0x8 3 *b = 1. Modificarea 0xE c = 10 halfbyte *b. *d. Exemplu didactic: procesor pe 4 biți 0xF a = 1 halfbyte a = 8. deci a devine 1 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 .

deci *(0xE +0) = 2 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0xD b = 15 variabilelor 0xC d = 14 0xB 11 b = &a. adică 14 0x9 0 0x8 3 *b = 1. Exemplu didactic: procesor pe 4 biți 0xF a = 1 halfbyte a = 8. adică d devine 0xE. c = 5. 0x7 13 0x6 5 d[0] = 2. 0xA 5 d = &c. *d. Modificarea 0xE c = 10 halfbyte *b.

adică d devine 0xE. *d. adică 14 0x9 0 0x8 3 *b = 1. Exemplu didactic: procesor pe 4 biți 0xF a = 1 halfbyte a = 8. 0xA 5 d = &c. deci *(0xE +0) = 2 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Modificarea 0xE c = 2 halfbyte *b. c = 5. 0xD b = 15 variabilelor 0xC d = 14 0xB 11 b = &a. 0x7 13 0x6 5 d[0] = 2.

0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. 0x9 0 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++.

0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++. 0x9 0 print(a). 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8.

0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++. afișează valoarea 8 0x8 3 0x7 13 0x6 5 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0x9 0 print(a).

0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++. 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. 0x8 3 inc(a). 0x7 13 0x6 5 print(a). 0x9 0 print(a).

afișează valoarea 8 0x5 12 De ce? Ce s-a întâmplat la apel? 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0x8 3 inc(a). 0x7 13 0x6 5 print(a). Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++. 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. 0x9 0 print(a).

0x9 0 print(a). 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. 0x7 13 0x6 5 Un apel de funcție: 0x5 12 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0x8 3 inc(a). Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++.

pe stivă. 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. 0x7 13 0x6 5 Un apel de funcție: 0x5 12 .Face o copie. a tuturor param 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 5 a++. 0x9 0 print(a). 0x8 3 inc(a).

a tuturor param 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . 0x9 0 print(a). Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 8 a++. 0x8 3 inc(a).Face o copie. pe stivă. 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8.

Face o copie. 0x8 3 inc(a). Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE ainc = 8 a++. pe stivă. a tuturor param 0x4 0 0x3 4 0x2 7 0x1 1 0x0 2 . 0x9 0 print(a). 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8.

0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. pe stivă. Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE ainc = 8 a++.Face o copie. 0x8 3 inc(a).Execută instrucțiuni în funcție 0x3 4 0x2 7 0x1 1 0x0 2 . 0x9 0 print(a). 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . a tuturor param 0x4 0 .

Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE ainc = 9 a++. pe stivă. a tuturor param 0x4 0 .Execută instrucțiuni în funcție 0x3 4 0x2 7 0x1 1 0x0 2 . 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . 0x9 0 print(a).Face o copie. 0x8 3 inc(a). 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8.

pe stivă.Execută instrucțiuni în funcție 0x3 4 . Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE ainc = 9 a++. 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . a tuturor param 0x4 0 . 0x8 3 inc(a). 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8.Golește stiva la terminarea apelului 0x2 7 0x1 1 0x0 2 .Face o copie. 0x9 0 print(a).

0x9 0 print(a). 0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 9 a++.Execută instrucțiuni în funcție 0x3 4 . pe stivă. 0x8 3 inc(a).Face o copie. 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . a tuturor param 0x4 0 .Golește stiva la terminarea apelului 0x2 7 0x1 1 0x0 2 .

0xD 14 } funcție 0xC 4 0xB 11 0xA 5 halfbyte a = 8. a tuturor param 0x4 0 . 0x8 3 inc(a). pe stivă.Golește stiva la terminarea apelului 0x2 7 0x1 1 print(a). 0x9 0 print(a). Exemplu didactic: procesor pe 4 biți 0xF a = 8 void inc(halfbyte a) { Apelul de 0xE 9 a++. 0x7 13 0x6 5 Un apel de funcție: 0x5 12 . afișează valoarea 8 0x0 2 .Execută instrucțiuni în funcție 0x3 4 .Face o copie.

Alocarea dinamică a memoriei .

Reminder Stivă (stack) vs Heap Stivă Heap • acces ff rapid • alocarea persistă și după • se curăță automat la terminarea funcției terminarea funcției • dimensiune nelimitată* • spațiul gestionat eficient (nu • ceva mai lentă se fragmentează) • trebuie să gestionăm noi memoria (rezervăm/alocăm și • doar pentru variabile locale eliberăm) • dimensiune (mai mică decât • nu este gestionată eficient (se heap-ul) dependentă de fragmentează) sistemul de operare [1] • putem redimensiona • dimensiunea variabilelor nu variabilele poate fi modificată *depinde totuși de memoria virtuală .

Stivă (stack) vs Heap Când folosim stiva? Când folosim heap-ul? • date de dimensiuni mici • date de dimensiuni mari • le folosim doar într-o • date care pot să-și schimbe funcție dimensiunea în timp • le știm de la început • date care trebuie să aibă dimensiunea maximă (și durată de viață mare aceasta nu se schimbă pe parcursul programului) .

null pointer • Cum știm că un pointer este valid (îl putem folosi)? – un pointer este o adresă de memorie. dacă scriem la o adresă pe care nu avem dreptul să o accesăm => segmentation fault • Cum diferențiem un pointer inițializat de un pointer neinițializat? – amândoi pointerii punctează la o adresă care poate fi validă .

a null pointer points definitively nowhere. it is not the address of any object or function. there is a special value--the ”null pointer”--which is distinguishable from all other pointer values and which is ”guaranteed to compare unequal to a pointer to any object or function. The address-of operator & will never yield a null pointer [3] • in C null pointer-ul este reprezentat ca NULL și are valoarea 0 • în teorie pot exista și reprezentări diferite de 0 în memorie pt NULL . null pointer (NULL) • avem nevoie de o adresă specială. care să nu fie validă niciodată și care să o atribuim pointerilor ce nu pot fi folosiți • The language definition states that for each pointer type.” That is.

null pointer (NULL) • int *p. • p=NULL. //p este inițializat cu NULL • if(p) //sau if(p!=NULL) – verifică dacă p are o adresă validă • trebuie să avem grijă ca atunci când un pointer nu mai are o adresă validă spre care să puncteze să-i fie asignat NULL • funcții care nu reușesc să returneze adrese valide folosesc returnează tot NULL .

• pentru a putea utiliza spațiul rezervat adresa de început a zonei de memorie este asignată unui pointer • în cazul în care alocarea nu reușește funcțiile de alocare întorc NULL . Alocarea dinamică a memoriei • alocarea dinamică a memoriei – rezervarea unui spațiu de memorie a cărui dimensiune o putem ști la compilare sau la rulare.

malloc • void* malloc (size_t size).h • size_t – unsigned long . • alocă un număr de size octeti • întoarce pointer la zona de date alocată sau NULL în cazul în care alocarea nu reușește • definită în stdlib.

Exemplu malloc

calloc
• void* calloc(size_t num, size_t size);
• num = numărul de elemente
• size = dimensiunea unui element
• toată zona de memorie alocată este inițializată cu
0
• ! ținând cont că NULL poate avea reprezentări pe
biți diferite de 0 dacă alocăm un vector de
pointeri nu este bine să ne bazăm pe inițializările
făcute de calloc
• take it with a grain of salt

Exemplu calloc

• redimensionează zona de memorie spre care punctează ptr la size octeți. întoarce NULL . realloc • void *realloc (void* ptr. • dacă size este mai mare decât dimensiunea inițială a blocului. zona suplimentară nu este inițializată • dacă realocarea nu reușește. size_t size).

• Este echivalent cu: ptr1 = malloc(.. . ptr2... realloc • In cele mai multe situatii. .). memcpy(ptr1.).). free(ptr2).. puteti considera ca ptr1=realloc(ptr2. ...

Exemplu realloc .

free • void free(void* ptr). • eliberează memoria alocată și spre care punctează pointerul ptr • dacă ptr punctează către o zonă de memorie care nu a fost alocată cu malloc. realloc comportarea este nedefinită • ptr nu este modificat de free. calloc. Este recomandat să îi asignăm NULL după apelul free .

Exemplu free .

• Cast-urile în cazul acesta sunt descurajate în C. alocare spatiu vectori • tip_vector *v. • v=(tip_vector*)malloc(nr_elemente*sizeof(tip_vector)).sizeof(tip_vector)). însă dacă vreți să compilați codul cu un compilator C++. • sau • v=(tip_vector*)calloc(nr_elemente. atunci acestea vor deveni obligatorii .

alocare spatiu matrice • vrem sa alocam spatiu pentru o matrice [m][n] • putem aloca un vector cu m*n elemente – trebuie sa avem grija sa accesam elementele corect (v[n*i+j]óv[i][j] • alocam un vector de m pointeri si pentru fiecare pointer alocam un vector de n elemente .

alocare matrice ca vector .

alocare matrice ca vector de pointeri • From [5] .

– if(!v) //if(v==NULL) – nu s-a putut efectua alocarea se tratează eroarea • nu se eliberează memoria – aveti grija sa faceti free de fiecare dată când folosiți alocare dinamică . Greșeli frecvente alocare • nu se verifică succesul alocării – v=(int*)malloc(n*sizeof(int)).

Greseli frecvente • erori de logică – se utilizează o zonă de memorie după ce a fost eliberată • nu se asigneaza pointerului NULL dupa eliberare si se acceseaza o zona de memorie care poate fi curatata sau poate sa mentina valorile (cel mai periculos) • nu se asigneaza pointerului NULL dupa eliberare si ajungem sa accesam o zona la care nu mai avem dreptul (seg fault) • asignam pointerului NULL dupa eliberare sau dupa eroare alocare dar nu verificam daca pointerul este diferit de NULL si incercam sa-l mai folosim .

spatiul pentru v este rezervat pe stiva incheierea functiei . malloc(n*sizeof(int)). return v..NU toate compilatoarele implementează . … } return v.spatiul pt v este limitat la dimensiunea v este alocat pe heap stivei . int *v=(int*) ….v puncteaza catre o zona de memorie } “curatata” la parasirea functiei spatiul rezervat pentru v exista si la . VLA vs vectori alocati dinamic • VLA • vectori alocati dinamic int* f(int n) int *f(int n) { { int v[n]. .

http://c-faq. http://gribblelab.wikipedia.h 5.org/wiki/C_data_types#stddef.txt 2. Bibliografie 1.nyu.html 4.edu/exact/core/doc/stackOverflow.html 3.cs.com/what-is-c/function-a-pointer/two-dimensional-arrays-using-a- pointer-to-pointer . http://en. http://ecomputernotes. http://www.org/CBootcamp/7_Memory_Stack_vs_Heap.com/null/index.