User Tools

Site Tools


dydaktyka:cprog:2016:dynamic_memory_allocation

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
dydaktyka:cprog:2016:dynamic_memory_allocation [2017/01/16 06:39]
pkleczek
— (current)
Line 1: Line 1:
-~~NOTRANS~~ 
- 
-====== Dynamiczna alokacja pamięci ====== 
- 
-W języku C można wyróżnić dwie podstawowe metody alokacji (przydzielania) pamięci: 
-  * **alokacja statyczna** -- ilość pamięci zostaje z góry określona na etapie pisania programu (poprzez odpowiednie deklaracje zmiennych); pamięć jest zwalniana automatycznie -- po zakończeniu bloku programu, w którym była deklarowana (chyba, że obiekt został zadeklarowany jako ''​static''​),​ lub po zakończeniu programu 
-    <code c> 
-    int a; 
-    char str[] = "​Hello!";​ 
-    float tab[5];</​code>​ 
-  * **alokacja dynamiczna** -- program przydziela dowolne ilości pamięci w trakcie pracy, poprzez wywołanie odpowiednich funkcji; pamięć musi być jawnie zwolniona (z użyciem odpowiedniej funkcji) 
-    <code c> 
-    int* tab; 
-    tab = malloc(5 * sizeof(*tab));​ 
-    free(tab);</​code>​ 
- 
-Dynamiczna alokacja pamięci pozwala przede wszystkim na: 
-  * utworzenie tablicy o rozmiarze obliczanym dopiero podczas działania programu 
-  * dostęp do zmiennych utworzonych wewnątrz funkcji po wyjściu z nich 
- 
-===== Przydzielanie pamięci – funkcja "​malloc"​ ===== 
- 
-Funkcja [[http://​www.cplusplus.com/​reference/​cstdlib/​malloc/?​kw=malloc|malloc()]] (od //memory allocation//​) rezerwuje blok wolnej pamięci o zadanym rozmiarze (w bajtach) i zwraca adres jego pierwszego bajtu. W przypadku nieznalezienia wymaganego obszaru ''​malloc()''​ zwraca wskaźnik zerowy (dla przypomnienia -- wskaźnik o wartości ''​0''​). 
- 
-Ponieważ rezerwowany blok może być zmienną dowolnego typu, funkcja ta zwraca uniwersalny "​wskaźnik na ''​void''"​. Przypisanie takiego wskaźnika do wskaźnika dowolnego innego typu jest operacją dozwoloną przez standard języka. 
- 
-Aby utworzyć tablicę typu ''​double''​ o zadanym rozmiarze z użyciem funkcji ''​malloc()''​ można napisać następujący kod: 
-<code c> 
-int rozmiar = 10; 
-double* tab; 
-tab = malloc(rozmiar * sizeof(*tab));​ 
-</​code>​ 
- 
-Powyższy kod zarezerwuje obszar pamięci dla 10 wartości typu wskazywanego przez ''​tab''​ (czyli ''​double''​) i przypisze adres wskaźnikowi ''​tab''​. Zauważ, że zmienna ''​tab''​ została zadeklarowana jako wskaźnik do pojedynczej wartości ''​double'',​ a nie do bloku 10 takich wartości. Dlaczego? Ponieważ nazwa tablicy jest zarazem adresem jej pierwszego elementu, powyższe przypisanie umożliwia korzystanie z ''​tab''​ jak ze zwykłej nazwy tablicy (np. ''​tab[0]''​ to wartość jej pierwszego elementu). 
- 
-===== Korzystanie z tablic dynamicznych ===== 
- 
-Z tablic utworzonych w sposób dynamiczny korzysta się identycznie jak z tablic utworzonych statycznie: 
-<code c> 
-int rozmiar = 10; 
-double* tab = malloc(rozmiar * sizeof(*tab));​ 
-tab[3] = 4; 
-printf("​%d\n",​ tab[3]); 
-</​code>​ 
- 
- 
-===== Zwalnianie pamięci – funkcja "​free"​ ===== 
- 
-Funkcja [[http://​www.cplusplus.com/​reference/​cstdlib/​free/?​kw=free|free()]] zwalnia dynamicznie przydzieloną pamięć (i tylko taką -- próba zwalniania pamięci przydzielonej statycznie to błąd). Argumentem funkcji ''​free()''​ jest adres obszaru pamięci do zwolnienia. 
- 
-Na przykład: 
-<code c> 
-double* tab; 
-tab = malloc(8 * sizeof(*tab));​ 
-free(tab); 
-</​code>​ 
- 
-:!: System operacyjny wyznacz limit pamięci, jaki może wykorzystać dany program -- jego przekroczenie powoduje "​ubicie"​ programu. Zapominając zwolnić przydzieloną pamięć można łatwo doprowadzić do //​[[https://​pl.wikipedia.org/​wiki/​Wyciek_pami%C4%99ci|wycieku pamięci]]//​ i w konsekwencji właśnie do przedwczesnego zakończenia programu... 
- 
-===== Zmiana rozmiaru bloku pamięci – funkcja "​realloc"​ ===== 
- 
-Funkcja [[http://​www.cplusplus.com/​reference/​cstdlib/​realloc/​|realloc()]] służy do zmiany rozmiaru zaalokowanego dynamicznie bloku pamięci. Jej pierwszym argumentem jest adres bloku pamięci, a drugim -- nowy rozmiar (w bajtach). 
- 
-Do zwalniania pamięci przydzielonej przez ''​realloc()''​ służy również funkcja ''​free()''​. 
- 
-Przykład: 
-<code c> 
-double* tab; 
-int rozmiar_1 = 10; 
-int rozmiar_2 = 20; 
- 
-tab = malloc(rozmiar_1 * sizeof(*tab));​ // pierwotnie `tab` ma rozmiar 10 bajtow 
-tab = realloc(tab,​ rozmiar_2 * sizeof(*tab));​ // teraz `tab` ma rozmiar 20 bajtow 
-free(tab); 
-</​code>​ 
- 
-===== Alokacja pamięci dla tablicy dwuwymiarowej ===== 
- 
-Aby utworzyć dynamiczną tablicę dwuwymiarową,​ możemy postąpić w następujący sposób: 
-Najpierw alokujemy pamięć dla "​wierszy",​ a następnie dla "​kolumn"​. Podczas zwalniania pamięci postępujemy na odwrót -- najpierw zwalniamy pamięć przydzieloną dla "​kolumn",​ a potem dla "​wierszy"​. 
- 
-Przykład: 
-<code c> 
-#include <​stdio.h>​ 
-#include <​stdlib.h>​ 
- 
-int main () 
-{ 
-    int w = 6;  //liczba wierszy 
-    int k = 3;  // liczba kolumn 
-    double **tab2d; 
-    int i; 
- 
-    tab2d = malloc(w * sizeof(double*)); ​ // alokacja pamięci "​wierszy"​ 
- 
-    for(i = 0; i < w; i++) { 
-        tab2d[i] = malloc(k * sizeof(double)); ​ // alokacja pamięci "​kolumn"​ 
-    } 
- 
-    for(i = 0; i < w; i++) { 
-        free(tab2d[i]);​ // zwolnienie pamieci kolumn"​ 
-    } 
- 
-    free(tab2d);​ //​uwolnienie pamieci "​wierszy"​ 
-    tab2d = NULL; 
- 
-    return 0; 
-} 
-</​code>​ 
- 
-Inne sposoby tworzenia dynamicznych tablic 2D przestawione są w artykule [[http://​www.geeksforgeeks.org/​dynamically-allocate-2d-array-c/​|How to dynamically allocate a 2D array in C?]] 
- 
- 
-===== Zadania podsumowujące ===== 
- 
-:!: W poniższych ćwiczeniach każdorazowo zadbaj o poprawne zwolnienie przydzielonej dynamicznie pamięci! 
-==== Zadanie DAL1D ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​1/​4}}) 
- 
-Napisz program który alokuje dynamicznie jednowymiarową tablicę (wybranego typu), wypełnia ją losowymi liczbami, a następnie wypisuje jej elementy na ekran. 
- 
-==== Zadanie DAL1DCHG ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​1/​4}}) 
- 
-Zmodyfikuj program z [[dydaktyka:​cprog:​2015:​dynamic_memory_allocation#​zadanie_dal1d|zadania DAL1D]] tak, aby po utworzeniu tablicy i zainicjalizowaniu jej elementów program powiększył jej rozmiar dwukrotnie (nowe elementy wypełniając zerami) i ponownie wypisał jej elementy na ekran. 
- 
-/* 
-==== Fotoszop ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​1/​4}}) 
- 
-Wykonaj zadania w ramach polecenia [[dydaktyka:​cprog:​2015:​photoshop:​exercises:​dynamic_image_allocation|Dynamiczna alokacja tablicy-obrazu]]. 
-*/ 
- 
-==== Zadanie DAL2D ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​2/​4}}) 
- 
-Napisz program który alokuje dynamicznie tablicę przechowującą w wierszach następujące wyrazy: 
-<​code>​ 
-Oto 
-tablica 
-dynamiczna. 
-</​code>​ 
  
dydaktyka/cprog/2016/dynamic_memory_allocation.1484545188.txt.gz · Last modified: 2020/03/25 11:46 (external edit)