1 / 27

ΗΥ - 150 Προγραμματισμός

ΗΥ - 150 Προγραμματισμός. Δυναμική Διαχείριση Μνήμης (1/2). Δυναμική Διαχείριση Μνήμης. Μέχρι τώρα στατική ανάθεση και δέσμευση μνήμης Ζητούσαμε στο π ρόγραμμά μας τη μέγιστη μνήμη π ου μ π ορεί να χρειαζόμασταν #define MAX_SIZE 10000 int array[MAX_SIZE];

fausta
Download Presentation

ΗΥ - 150 Προγραμματισμός

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ΗΥ-150Προγραμματισμός ΔυναμικήΔιαχείρισηΜνήμης (1/2)

  2. ΔυναμικήΔιαχείρισηΜνήμης • Μέχριτώραστατικήανάθεσηκαιδέσμευσημνήμης • Ζητούσαμεστο πρόγραμμάμαςτημέγιστημνήμη πουμπορείναχρειαζόμασταν • #define MAX_SIZE 10000 • int array[MAX_SIZE]; • Μειονέκτημα : Υπάρχουνεφαρμογές πουτοMAX_SIZEείναιάγνωστοοπότεαναγκαζόμαστεναδηλώνουμεμεγάλεςτιμέςκαιναχάνουμεκαισεμνήμηκαισεταχύτητα • Δυναμικήκατανομήμνήμης (dynamic memory allocation) • Αίτησηαπότολειτουργικόναμας παραχωρήσειμνήμη • Ειδοποίησηστολειτουργικόότιδενχρειαζόμαστε πιαέναμέροςμνήμης • Ό,τιδεσμεύετε πρέπεινααποδεσμεύετε

  3. ΚατηγορίεςΜνήμηςτουΠρογράμματοςΚατηγορίεςΜνήμηςτουΠρογράμματος • Μνήμηαποθήκευσηςτουκώδικατου προγράμματος • Μνήμηαποθήκευσηςτωνμεταβλητώνενός προγράμματος πουδεσμεύονταιμεστατικήήαυτόματηδιαχείρισημνήμης • Αυτήημνήμηονομάζεταιστοίβα(stack) • Μνήμηαποθήκευσηςτωνμεταβλητώνενός προγράμματος πουδεσμεύονταιμεδυναμικήδιαχείρισημνήμης • Αυτήημνήμηονομάζεταισωρός (heap)

  4. ΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμηςΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμης • Βρίσκονταιστηνstdlib.h • void *malloc( size_t numBytes); • ΔεσμεύειnumBytes αριθμόαπόδιαδοχικάBytes καιεπιστρέφειέναδείκτηστηναρχήτηςδεσμευμένηςθέσημνήμης • ΕπιστρέφειNULL ανδενμπορείναδεσμεύσειάλλημνήμη int *ptr = (int *) malloc (100*sizeof(int));

  5. ΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμηςΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμης • void *calloc(size_t nelements, size_t bytes); • Δεσμεύειnelements αριθμόαπόδιαδοχικάαντικείμενατοκαθέναμεγέθουςbytes καιεπιστρέφειέναδείκτηστηναρχήτηςδεσμευμένηςθέσημνήμης • ΕπιστρέφειNULL ανδενμπορείναδεσμεύσειάλλημνήμη • Αρχικοποιείτα περιεχόμενατηςδεσμευμένηςμνήμηςστο 0 • Παρόμοιαμετηνmalloc • Διαφορά 1: λίγοδιαφορετικήκλήση • Διαφορά 2: αρχικοποίησητων περιεχομένωνμε 0 int *ptr = (int *) calloc (100, sizeof(int));

  6. ΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμηςΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμης • void free(void *pointer); • Αποδεσμεύειτημνήμη πουέχειδεσμευτείμεμίααπότις προηγούμενεςκλήσειςστηνmalloc, calloc ήrealloc • Δεν πρέπεινααποδεσμεύουμε πάνωαπόμιαφοράτηνίδιαμνήμη ptr= (int *)malloc (100*sizeof(int)); free(ptr); // Αυτόείναιοκμέχριεδώ free(ptr); // Αποδεσμεύουμετηνίδιαμνήμη // δυοφορές! ΛΑΘΟΣ

  7. ΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμηςΣυναρτήσειςΔυναμικήςΔιαχείρισηςΜνήμης • void *realloc(void *ptr, size_t size); • Επέκτασημνήμης • Οδείκτης*ptr πρέπειναδείχνεισεμνήμηήδηδεσμευμένημετηνmalloc ήcalloc • ptr= (int *)malloc (100*sizeof(int)); • Επαναδέσμευσημνήμηςμεάλλομέγεθος • ptr= (int *)realloc(ptr, 200*sizeof(int)); • Τα προηγούμενα περιεχόμενατηςδεσμευμένηςμνήμηςδιατηρούνται (τουλάχιστονόσαχωρούνστηνκαινούργια) • Ηκαινούργιαμνήμημπορείναείναισεάλληδιεύθυνσηανδενυπήρχεαρκετάμεγάλοσυνεχόμενοblockαπόελεύθερημνήμηγιαδέσμευση. Σεαυτήντην περίπτωσηγίνεταιμεταφοράτωνδεδομένωνκαιαποδεσμεύεταιημνήμηptr, σανναγίνεταιδηλαδήμιαfree(ptr)

  8. Οτύποςvoid* • Γενικόςδείκτης • Κατάτηνεκτέλεσητου προγράμματοςαποφασίζετεοτύποςτου(char *, int *, float *, double *, struct my_struct *, …) • Ογενικόςδείκτηςμαςδίνειτηδυνατότηταναορίζουμεσυναρτήσεις πουμαςεπιστρέφουμεχώροστημνήμηχωρίςναμαςενδιαφέρειοτύπος! Π.χ. malloc • ΠΡΟΣΟΧΗ: σεσυναρτήσειςείναιτελείωςδιαφορετικό 1. void f() // ησυνάρτησηΔΕΝεπιστρέφειτίποτα 2. void *f() //επιστρέφειέναδείκτη πουο προγραμματιστής πρέπεινα //αποσαφηνίσειτοντύποτουμέσαστηνσυνάρτηση

  9. ΔυναμικοίΠίνακες • Πίνακες πουτομέγεθοςτουςκαθορίζεταικατάτηνεκτέλεσητου προγράμματος ( σεrun-time). • Δυνατότητα προσαρμογήςστιςεκάστοτεαπαιτήσειςχωρίςανάγκη περιορισμού. • int *x = (int *)malloc( 10 * sizeof(int)); x

  10. Πρόβλημα 1: ΑποτυγχάνειηΔέσμευση • Πρέπειναγίνεταιπάνταέλεγχοςεπιστροφήςτηςαπαραίτητηςμνήμης!! • Είναιευθύνητου προγραμματιστήκαιστοιχείοσωστού προγραμματισμού! • ΟισυναρτήσειςδυναμικήςδέσμευσηςεπιστρέφουνNULL όταναποτυγχάνουν, τοοποίομπορούμεναεξετάσουμεκαιναδιακόψουμετηνεκτέλεσητου προγράμματοςανχρειάζεται int *p = (int *)malloc(10000*sizeof(int)); if (p == NULL) { printf( “No Memory Available\n”); exit(0); }

  11. Πρόβλημα 2: ΔιαρροήΜνήμης • Απελευθέρωση • Πρέπειναελευθερώνουμετηνμνήμηότανδεντηνχρειαζόμαστε (μετηνfree) • Δενελευθερώνουμε ποτέμνήμη πουδενέχειαποκτηθείδυναμικά (λ.χ. μεmalloc) • Ανδενελευθερώσουμεόλητημνήμη πουδεσμεύουμεαυτόονομάζεταιδιαρροήμνήμης (memory leak) • Ηδιαρροήμνήμηςμπορείναοδηγήσεισεκαταστάσεις πουδενυπάρχειάλληελεύθερημνήμη • Προχωρημένο: όταντελειώνειηελεύθερημνήμητουυπολογιστή, τότετολειτουργικόστέλνεικάποιαμνήμηστονδίσκο, ελευθερώνειέτσιμνήμηκαιτηνξανα-χρησιμοποιεί. Ξαναφέρνειαπότονδίσκοστημνήμηότανγίνεται πρόσβασησεαυτήν. Αυτόοδηγείστοφαινόμενοtrashing όπουγράφεταικαιδιαβάζεταιαπότοδίσκοσυνέχειαμνήμη. Μεδιαρροήμνήμηςένα πρόγραμμαμπορείνααρχίσεινακάνειthrashing μετάαπόώρες, μέρες, ήχρόνιασυνεχήςλειτουργίαςτου. • Λύση:Αποδεσμεύουμεαμέσωςτημνήμη πουδενχρησιμοποιούμε (χρήσητηςfree)

  12. Πρόβλημα 3: • ΧρήσηΜετάτηνΑποδέσμευση • Κάνουμεfree καιμετάξαναχρησιμοποιούμετηνίδιαμνήμη • Παρόμοιααποτελέσματαότανχρησιμοποιούμεμηδεσμευμένημνήμη • Αλλάζουμεμεταβλητές πουχρησιμοποιούμεχωρίςνατοξέρουμε – δύσκολαανιχνεύεται • Πάμεναγράψουμεσεμνήμη πουδενμαςανήκει (segmentation fault)καιτο πρόγραμμαδιακόπτεταιαυτόματα

  13. Πρόβλημα 4: • Αποδέσμευσημνήμης πουδενέχουμεδεσμεύσει • Μπορείναμπερδέψειτολειτουργικόστηνδιαχείρισηελεύθερηςμνήμης

  14. ΗΥ-150Προγραμματισμός ΔυναμικήΔιαχείρισηΜνήμης (2/2)

  15. Δείκτεςσεδείκτες • char ch; char *pch; char **ppch;char ***ppch; • Δείκτηςσε πίνακααπόδείκτες (άγνωστοστηναρχήκαιτομέγεθοςτου πίνακακαιτομέγεθοςτων περιοχών πουδείχνουνοιδείκτες)

  16. Δείκτεςσεδείκτες A[0][0] A[0][1] A[0][2] … A[0] A[1][0] ... A[1] A[2][0] ... A[i][j] A[2] A[3][0] ... A[3] A[4] A[4][0] ...A[4][9] #include <stdio.h> #include <stdlib.h> int main(void) { int lines = 5; /* Both lines and cols could be evaluated */ int cols = 10; /* or read in at run time */ int i, **Α; A = (int **)malloc(lines * sizeof(int *)); if (A == NULL) { puts("\nFailure to allocate room for row pointers.\n"); exit(0); } for (i = 0; i < lines; i++) { Α[i] = (int *) malloc(cols * sizeof(int)); if (Α[i] == NULL) { printf("\nFailure to allocate for row[%d]\n",i); exit(0); } printf("\n%d %p %d", i, Α[i], Α[i]); if (i > 0) printf(" %d",(int)(Α[i] - Α[i-1])); } //free the memory for (i = 0; i < lines; i++) free (Α[i]); free(A); return 0; } Εφαρμογή: πίνακας - εικόνα A

  17. A = (int **)malloc(lines * sizeof(int *)); • if (A == NULL) • { • puts("\nFailure to allocate room for row pointers.\n"); • exit(0); • } • for (i = 0; i < lines; i++) • { • Α[i] = (int *) malloc(cols * sizeof(int)); • if (Α[i] == NULL) • { • printf("\nFailure to allocate for row[%d]\n",i); • exit(0); • } • printf("\n%d %p %d", i, Α[i], Α[i]); • if (i > 0) printf(" %d",(int)(Α[i] - Α[i-1])); • }

  18. //free the memory • for (i = 0; i < lines; i++) • free (Α[i]); • free(A);

  19. Συνοπτικά … • Έχουμε: int x; int *px; px = &x • Καιέναακόμαβήμα: int **ppx; ppx = &px; • Οπότεμπορούμενακάνουμε: **ppx = 42; /* Puts 42 into x */ • Αλλάόχι: *ppx = 42; /* ERROR!! */

  20. Visually ADDR CONT SYMB int x; int *px; int **ppx; px = &x ppx = &px; **ppx = 42; 1000 42 x 2000 1000 px 3000 2000 ppx

  21. ΠΡΟΣΟΧΗ! • ΔείκτεςσεΔείκτεςέναντιΔυσδιάστατουςΠίνακες • int a[10][20]; • a[r][c] είναισυντακτικάαποδεκτό • Δέσμευσημνήμης: 10×20 ακέραιοι • Υπολογισμόςδιεύθυνσηςτουa[r][c]: r*20+c+αρχήτου πίνακα • int **b; • b[r][c] είναισυντακτικάαποδεκτό • Δέσμευσημνήμηςγιαb:10 δείκτες b = (int **)malloc (10*sizeof(int*)) • Δέσμευσημνήμηςγιαb[i]: 20 ακέραιοισεκάθεγραμμή for (i = 0; i < 10; i++) b[i] = (int *) malloc(20 * sizeof(int)); • Υπολογισμόςδιεύθυνσηςτουb[r][c]: διεύθυνσημνήμηςτουδείκτηb[r] + c • ΠΡΙΝΤΟΝΥΠΟΛΟΓΙΣΜΟΤΟΥb[r][c] πρέπειναέχειγίνεισωστήανάθεσητιμώνσταb[r]καιδέσμευσημνήμης.

  22. Strings • Χρήσηδεικτώνγιατηνδιαχείριση strings • Όπωςέχουμε πει: int a[ ] = {0, 1, 3, 5} • Καιηδιάστασηθακαθοριστείσε a[4] • Επίσης: char b[ ] = {‘t’, ‘e’, ‘s’, ‘t’, ‘\0’}  char c[ ] = “test”;

  23. Όμως … char aLine[ ] = “Hi, there!”; char *pLine = “Hi, there!”; • Παρόμοιααλλάόχιταίδια!!! • Το πρώτοκαθορίζειέναν πίνακαχαρακτήρων (11) πουμπορείνααλλαχθεί: aLine[4] = ‘T’; /* Σωστό! */ • Τοδεύτεροκαθορίζειένανδείκτη προςμίασταθεράτύπουstring πουδενμπορείνααλλαχθεί: pLine[4] = ‘T’; /* ΛΑΘΟΣ!! */ • Ενώαν: pLine = aLine; pLine[4] = ‘T’; /* Σωστό! */

  24. Κιάλλα … • Όχιμόνοδείκτεςσεδείκτεςαλλάκαι πίνακεςαπόδείκτες! • char *name[ ] = {“Illegal”, “Jan”, ”Feb”, ”Mar”, ”Apr”, ”May”, “Jun”, “Jul”, “Aug”, “Sep”, “Oct”, “Nov”, “Dec”}; • Π.χ. name[2] είναιέναςδείκτηςστο character string ‘F’, ‘e’, ‘b’, ‘\0’ • Γιατίθαθέλαμεέναν πίνακααπόδείκτες;

  25. Φανταστείτε : • Έχουμεονόματαόπως: • Smith, David • Leahy, Bill • Dagon, David • Humperdinck, Englebert • Υποθέστε πωςθέλουμεναταταξινομήσουμεαλφαβητικάαλλά παρατηρούμε πωςείναιδιαφορετικούμεγέθους. • Αντίναχρησιμοποιήσουμεέναναλγόριθμοταξινόμησης πουαλλάζειcharacter strings around γιατίναμηνχρησιμοποιήσουμεέναν πίνακααπόδείκτεςκαινααλλάζουμεδείκτες; • πολύ πιογρήγορο

  26. Έχουμεέναν πίνακααπό pointers name[0] Smith, David name[1] Leahy, Bill name[2] Dagon, David name[3] Humperdinck, Englebert

  27. Ταξινόμησημεμετακίνησηδεικτών name[0] Smith, David name[1] Leahy, Bill name[2] Dagon, David name[3] Humperdinck, Englebert

More Related