W08.PDF

(61 KB) Pobierz
w8.dvi
ZARZA DZANIE
PAMIE CIA
Standardowe funkcje malloc i calloc dynamicznie pobieraja
od systemu »adane bloki pamieci.
void *realloc(void *p, size_t size);
Funkcja real loc zmienia rozmiar obiektu wskazywanego przez p
na warto±¢ okre±lona przez size. Zawarto±¢ obiektu nie ulegnie
zmianie w jego cze±ci poczatkowej o rozmiarze równym mniej-
szemu z rozmiarów: starego i nowego. Je±li nowy rozmiar jest
wiekszy, to dodatkowy obszar pamieci nie jest inicjowany.
Funkcja zwraca wska¹nik do nowego obszaru lub NULL, je±li
polecenie nie mo»e by¢ wykonane. Wówczas wska¹nik p nie ulega
zmianie.
void *malloc(size_t n);
Zwraca:
wska¹nik do n bajtow nie zainicjowanej pamieci w przy-
padku powodzenia
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
NULL, gdy »adanie nie mo»e by¢ speªnione.
Przykªad:
int main(void)
{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
char *str;
/* allocate memory for string */
str = (char *) malloc(10);
/* copy "Hello" into string */
strcpy(str, "Hello");
printf("String is %s\n Address is %p\n", str, str);
str = (char *) realloc(str, 20);
printf("String is %s\n New address is %p\n",
str, str);
/* free memory */
free(str);
return 0;
int main(void)
{
char *str;
/* allocate memory for string */
if ((str = (char *) malloc(10)) == NULL)
{
printf("Not enough memory to allocate buffer\n");
exit(1); /* terminate program if out of memory */
}
}
/* copy "Hello" into string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
return 0;
Zwolnienie przydzielonej pamieci
void free(void *p);
}
void *calloc(size_t obj, size_t size);
Funkcja free zwalnia obszar pamieci wskazywany przez p ;nie
robi nic, je±li p równa sie NULL.
Argument p musi by¢ wska¹nikiem do obszaru uprzednio
przydzielonego przez jedna z funkcji: malloc, calloc, realloc .
Ró»nica miedzy standardowadeklaracjatablicy,ajej
dynamicznaalokacja
Funkcja calloc zwraca wska¹nik do obszaru pamieci przezna-
czonego dla tablicy zªo»onej z nobj elementów, ka»dy o rozmiarze
size .
Funkcja zwraca NULL, je±li to polecenie nie mo»e by¢ wy-
konane. Obszar jest inicjowany zerami.
1) char hello[5];
2) char *hello=(char *) malloc((size_t) 5);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
1. pamie¢ przydzielana do pamieci stosu (stack memory),
która jest ponownie wykorzystywana po zako«czeniu dzia-
ªania funkcji
int main(void)
{
2. przydziaª do pamieci sterty - heap (heap memory - sterta
zmiennych dynamicznych w pamieci operacyjnej.
char *str = NULL;
/* allocate memory for string */
str = (char *) calloc(10, sizeof(char));
/* copy "Hello" into string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
return 0;
Heap memory - caªa pamie¢ za wyjatkiem bufora pamieci stosu
(oraz bufora bezpiecze«stwa wokóª stosu.
Uwaga:
bªedem jest zwalnianie czegos, co nie zostaªo przydzielone
za pomoa funkcji malloc lu/b cal loc
}
bªedem jest równie» u»ywanie czego±, co zostaªo zwolnione
Uwaga: Warto±¢ wska¹nika zwracanego przez obydwie funkcje
trzeba zrzutowa¢ na odpowiedni typ.
Zmiana wielko±ci przydzielonego obszaru
Typowym i niepoprawnym fragmentem programu jest
nastepujaca petla, która zwalnia bloki pamieci powiazane w ªa«-
cuch:
for (p=head; p != NULL; p=p->next) /* Zle */
free(p);
opuszczenie w deklaracji tablicy okre±lenia liczby elemen-
tów w pierwszym wymiarze tablicy powoduje domniema-
nie go na podstawie listy inicjatorów.
Poprawnie nalezy przechowywac wszystko, co jeszcze
bedzie potrzebne przed zwolnieniem pamieci:
Przykªady:
for (p=head; p != NULL; p=q) {
q=p->next;
free(p);
int Vec[3]={10,20,30};
long int Arr[3][2]={ {1,2}, {3,4}, {5,6}};
char Greet[6]={'H','e','l','l','o'};
/* Greet[6] przypisano domy\' slnie '\0' */
char Text[]="Hello World";
/* domniemany rozmiar 12 */
short int Matrix[2][3]={{1,2},{3}};
/* domniemany inicjator {{1,2,0},{3,0,0}} */
}
Tablice wielowymiarowe
Zasady:
tablica dwuwymiarowa jest jednowymiarowa tablica, w
której ka»dy element jest tablica jednowymiarowa
Wska¹niki a tablice wielowymiarowe
Po nastepujacych denicjach:
dopuszczalne jest niedookre±lenie pierwszego wymiaru
(jego okre±lenie nastepuje wówczas w momencie inicjali-
zacji), natomiast nastepne musza by¢ sprecyzowane
int a[10][20];
int *b[10];
elementy sa umieszczane w pamieci wierszami, tzn. odwo-
ªanie
oba zapisy a[3][4] i b[3][4] sa poprawnymi odwoªaniami do poje-
dy«czego obiektu typu int.
daytab[i][j] /* [wiersz][kolumna] */
oznacza odniesienie do wiersza i-tego,
kolumny j-tej. (Najszybciej zmienia
si\c e prawy skrajny indeks.
a jest prawdziwa tablica wielowymiarowa, zarezerwo-
wano dla niej 200 miejsc o rozmiarze int; l -
ment a[wiersz][kolumna] znajduje sie wedªug wzoru:
20*wiersz+kolumna
Przykªad:
b przydziela jedynie 10 miejsc na wska¹niki i nie inicjuje ich;
nadanie warto±ci poczatkowych musi by¢ zrobione jawnie
- statycznie lub programowo.
Je±li ka»dy z elementów tablicy b wskazuje na tablice20
elementów caªkowitych. Wówczas mamy zarezerwowane
200 miejsc rozmiaru int plus 10 komórek na wska¹niki.
static char daytab[2][13]={
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,28,31,30,31,30,31,31,30,31,30,31}};
/* podaj dzien roku na podstawie miesiaca i dnia */
int day_of_year(int year, int month, int day)
{
Wa » n a przewaga tablicy wska¹ników jest mo»liwo±¢ zró»nico-
wania dªugo±ci wierszy.
Przekazywanie tablicy dwuwymiarowej do funkcji
Musimy poda¢ liczbe kolumn. Zatem, je±li tablica daytab ma
by¢ przekazana do funkcji f , to deklaracja funckji powinna mie¢
jedna z trzech poni»szych postaci:
int i,leap;
leap=year % 4 == 0 && year % 100 != 0
|| year % 400 == 0;
for (i=1; i<month; i++)
day += daytab[leap];
return day;
}
/* podaj miesiac i dzien na podstawie dnia roku */
void month_day(int year, int yearday,
int *pmonth, int *pday)
f(int daytab[2][13]);
f(int daytab[][13]);
{
f(int (*daytab)[13]);
int i,leap;
leap=year % 4 == 0 && year % 100 != 0
|| year % 400 == 0;
for (i=1; yearday > daytab[leap][i]; i++)
yearday -= daytab[leap][i];
*pmonth=i;
*pday=yearday;
Ostatnia deklaracja mówi, »e daytab jest wska¹nikiem do ta-
blicy 13 liczb caªkowitych. Nawiasy okragªe sa w tym przypadku
konieczne, poniewa» nawiasy kwadratowe [] majawy»szyprio-
rytet ni» operator adresowania po±redniego *. Bez nawiasów
okragªych deklaracja
}
int *daytab[13];
Inicjowanie tablic wielowymiarowych
wprowadza tablice13wska¹nikówdoobiektówcaªkowitych.
Mo»liwo±¢ korzystania z tablic wielowymiarowych o indeksach
ujemnych
Rozwiazanie przyjete przez autorów Numerical Recipes:
Lista inicjatorów jej elementów ujeta w nawiasy klamrowe.
Je±li w pewnym nawiasie klamrowym zabraknie elemen-
tów, to uzupeªnia sie zerami ( {0} ).
Je±li w pewnych nawiasach
wewnetrznych zostana wymienione
wszystkie inicjatory, to nawiasy takie mo»na pomina¢.
#include <stdlib.h>
#include <stdio.h>
#define TYPFLOAT long double
#define MSQRT sqrtl
#define MFABS fabsl
nawiasy klamrowe zawierajace listezmakówmo»na
zastapi¢ napisem-ªa«cuchem skªadajacym sieztakichwªa-
±nie znaków.
void nrerror(char error_text[])
{
/* Funkcja odczytu i tworzenia listy */
void czytanie(t_element **adpocz)
{ char nazwwe[DL_NAZW+1]; /* nazwisko czytane */
t_element *temp; /* na zamiane wsk. */
*adpocz=NULL; /* na poczatku lista pusta */
while (1) {
printf("nazwisko: ");
gets(nazwwe);
if (strlen(nazwwe)) {
temp=(t_element *) malloc(sizeof(t_element));
strcpy(temp->nazw,nazwwe);
printf("wiek: ");
scanf("%d", &temp->wiek);
getchar(); /* przeskakuje znak \n */
temp->nast=*adpocz;
*adpocz=temp;
fprintf(stderr,
"Numerical Recipes run-time error...\n");
fprintf(stderr,"%s\n",error_text);
fprintf(stderr,"...now exiting to system...\n");
exit(1);
}
TYPFLOAT **dmatrix(int nrl,int nrh,int ncl,int nch)
{
int i;
TYPFLOAT **m;
m=(TYPFLOAT **)
malloc((unsigned) (nrh-nrl+1)*sizeof(TYPFLOAT*));
if (!m) nrerror("allocation failure 1 in dmatrix()");
m -= nrl;
}
else break; /* wyjscie, gdy nazwisko puste */
}
for(i=nrl;i<=nrh;i++) {
m[i]=(TYPFLOAT *)
malloc((unsigned) (nch-ncl+1)*sizeof(TYPFLOAT));
if (!m[i])
nrerror("allocation failure 2 in dmatrix()");
m[i] -= ncl;
}
/* Funkcja wyprowadzania zawartosci listy */
void pisanie(t_element *poc)
{ printf("\n\n NAZWISKO
WIEK\n\n");
while (poc) {
printf("%20s %3d\n",poc->nazw, poc->wiek);
poc=poc->nast;
}
return m;
}
}
}
void free_dmatrix(TYPFLOAT **m,
int nrl,int nrh,int ncl,int nch)
{
int i;
for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
free((char*) (m+nrl));
}
Odwoªania do funkcji dmatrix mogawyglada¢ nastepujaco:
TYPFLOAT **Q;
/* ....... */
Q=dmatrix(-10,N,-5,N);
Struktury odwoªujace siedosamychsiebie-tworzenie
listy
Lista -uporzadkowany ciag elementów, z których ka»dy zawiera
wska¹nik do nastepnego elementu.
Drzewo -uporzadkowany ciag elementów, z których ka»dy za-
wierawska¹nikdonastepnego i poprzedzajacego elementu.
Przykªad (program tworzacy liste danych wczytywanych z kla-
wiatury i wypisujacy ja):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DL_NAZW 20 /* maks. dl. nazwiska */
typedef struct element /* def. typu element */
{ char nazw[DL_NAZW+1]; /*nazwisko */
int wiek; /* wiek */
struct element *nast; /* wsk. do nast. el. */
} t_element;
void main()
{ void czytanie(t_element **); /* f. tworzaca */
void pisanie(t_element *); /* f. wypisujaca*/
t_element *poczatek; /*wsk. do poczatku listy*/
czytanie(&poczatek);
pisanie(poczatek);
}
Zgłoś jeśli naruszono regulamin