Λειτουργία malloc() στη βιβλιοθήκη C με EXAMPLE
⚡ Έξυπνη Σύνοψη
Η malloc() στη C δεσμεύει ένα μπλοκ μνήμης στο σωρό κατά τον χρόνο εκτέλεσης και επιστρέφει έναν δείκτη void στο πρώτο byte του, επιτρέποντας στα προγράμματα να ζητήσουν χώρο αποθήκευσης του οποίου το μέγεθος είναι άγνωστο μέχρι να εκτελεστεί ο κώδικας.

Τι είναι το malloc στο C;
Η συνάρτηση malloc() σημαίνει εκχώρηση μνήμης. Είναι μια συνάρτηση που χρησιμοποιείται για την δυναμική κατανομή ενός μπλοκ μνήμης. Διατηρεί χώρο μνήμης καθορισμένου μεγέθους και επιστρέφει τον μηδενικό δείκτη που δείχνει στη θέση μνήμης. Ο δείκτης που επιστρέφεται είναι συνήθως τύπου void. Σημαίνει ότι μπορούμε να εκχωρήσουμε συνάρτηση malloc σε οποιονδήποτε δείκτη.
Σύνταξη
ptr = (cast_type *) malloc (byte_size);
Εδώ,
- Το ptr είναι δείκτης cast_type.
- Η συνάρτηση malloc επιστρέφει έναν δείκτη στην εκχωρημένη μνήμη byte_size.
Example: ptr = (int *) malloc (50)
Όταν αυτή η δήλωση εκτελεστεί με επιτυχία, δεσμεύεται ένας χώρος μνήμης 50 byte. Η διεύθυνση του πρώτου byte του δεσμευμένου χώρου εκχωρείται στον δείκτη ptr του τύπου int.
Εξετάστε ένα άλλο παράδειγμα εφαρμογής malloc:
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
Παραγωγή:
Value of the 6th integer is 480
Παρατηρήστε ότι χρησιμοποιήθηκε η συνάρτηση sizeof(*ptr) αντί για την συνάρτηση sizeof(int) προκειμένου να γίνει ο κώδικας πιο αξιόπιστος όταν η δήλωση *ptr τυποποιηθεί σε διαφορετικό τύπο δεδομένων αργότερα.
Η εκχώρηση ενδέχεται να αποτύχει εάν η μνήμη δεν είναι επαρκής. Σε αυτήν την περίπτωση, επιστρέφει έναν δείκτη NULL. Επομένως, θα πρέπει να συμπεριλάβετε κώδικα για να ελέγξετε εάν υπάρχει δείκτης NULL.
Λάβετε υπόψη ότι η εκχωρημένη μνήμη είναι συνεχόμενη και μπορεί να αντιμετωπιστεί ως πίνακας. Μπορούμε να χρησιμοποιήσουμε δείκτης αριθμητική για την πρόσβαση στα στοιχεία του πίνακα αντί για τη χρήση αγκυλών []. Σας συμβουλεύουμε να χρησιμοποιείτε το + για να αναφερθείτε σε στοιχεία του πίνακα, επειδή η χρήση της αύξησης ++ ή += αλλάζει τη διεύθυνση που αποθηκεύεται από τον δείκτη.
Η συνάρτηση Malloc μπορεί επίσης να χρησιμοποιηθεί με τον τύπο δεδομένων χαρακτήρων καθώς και με πολύπλοκους τύπους δεδομένων όπως δομές.
Γιατί να χρησιμοποιήσω malloc() σε C;
Οι στατικοί πίνακες και οι συνηθισμένες μεταβλητές καθορίζουν το μέγεθός τους κατά τη μεταγλώττιση του προγράμματος, κάτι που σπαταλά χώρο όταν η απαίτηση αποδεικνύεται μικρότερη και αποτυγχάνει εντελώς όταν αποδεικνύεται μεγαλύτερη. Η malloc() λύνει αυτό το πρόβλημα ζητώντας μνήμη κατά τον χρόνο εκτέλεσης, έτσι ώστε ένα πρόγραμμα να μπορεί να προσαρμόσει το μέγεθος ενός buffer στην ακριβή ποσότητα δεδομένων που λαμβάνει. Αυτή η ευελιξία κατά τον χρόνο εκτέλεσης είναι η καρδιά του... δυναμική κατανομή μνήμης στο Γ.
Η δυναμική κατανομή με malloc() είναι η σωστή επιλογή σε αρκετές συνηθισμένες περιπτώσεις:
- Η ποσότητα των δεδομένων εισόδου είναι άγνωστη μέχρι να εκτελεστεί το πρόγραμμα, όπως η ανάγνωση ενός αρχείου ή μιας λίστας που παρέχεται από τον χρήστη.
- Απαιτούνται μεγάλα μπλοκ που θα υπερχείλιζαν την περιορισμένη στοίβα, καθώς η malloc() αντλεί από τον πολύ μεγαλύτερο σωρό.
- Τα δεδομένα πρέπει να ζουν περισσότερο από τη συνάρτηση που τα δημιούργησε, επειδή η μνήμη σωρού παραμένει μέχρι να απελευθερωθούν ρητά.
- Οι δομές και οι πίνακες πρέπει να αυξάνονται ή να συρρικνώνονται κατά την εκτέλεση του προγράμματος.
Επειδή το δεσμευμένο μπλοκ επιστρέφεται ως δείκτης, μπορεί να μεταβιβαστεί μεταξύ συναρτήσεων φθηνά χωρίς να αντιγραφούν τα υποκείμενα δεδομένα.
Πώς να ελευθερώσετε μνήμη που έχει διατεθεί από το malloc()
Η μνήμη που δεσμεύεται από την malloc() βρίσκεται στο σωρό και δεν απελευθερώνεται ποτέ αυτόματα. Όταν ένα πρόγραμμα συνεχίζει να εκχωρεί χωρίς να απελευθερώνει, καταναλώνει αργά όλη τη διαθέσιμη μνήμη, ένα ελάττωμα γνωστό ως διαρροή μνήμης. Η συνάρτηση free() επιστρέφει ένα ολοκληρωμένο μπλοκ στο σύστημα, ώστε ο χώρος να μπορεί να επαναχρησιμοποιηθεί.
Η συνάρτηση free() δέχεται ένα μόνο όρισμα, τον δείκτη που επέστρεψε η malloc(), και απελευθερώνει ολόκληρο το μπλοκ ταυτόχρονα:
int *ptr; ptr = malloc(10 * sizeof(int)); if (ptr != NULL) { /* use the allocated memory here */ free(ptr); /* release the block */ ptr = NULL; /* avoid a dangling pointer */ }
Ακολουθήστε αυτούς τους κανόνες για να διαχειριστείτε με ασφάλεια τη δυναμική μνήμη:
- Καλέστε τη free() ακριβώς μία φορά για κάθε επιτυχημένη malloc(). Η απελευθέρωση του ίδιου μπλοκ δύο φορές προκαλεί απροσδιόριστη συμπεριφορά.
- Ορίστε τον δείκτη σε NULL μετά την απελευθέρωση, ώστε να μην μπορεί να επαναχρησιμοποιηθεί ως κρεμαστός δείκτης.
- Ποτέ δεν free() ένας δείκτης που δεν επέστρεψε η malloc(), συμπεριλαμβανομένου ενός δείκτη που μετατοπίστηκε κατά αριθμητική ένδειξη.
- Αντιστοιχίστε κάθε κατανομή με μια αντίστοιχη έκδοση πριν ο δείκτης βγει εκτός εμβέλειας.
Keeping Η κατανομή και η απελευθέρωση σε ισορροπία είναι ο βασικός κλάδος της χειροκίνητης διαχείρισης μνήμης στη C και αποτρέπει τόσο τις διαρροές όσο και τα σφάλματα που προκαλούνται από την επαναχρησιμοποίηση της απελευθερωμένης μνήμης.
malloc() vs calloc(): Βασικές διαφορές
malloc() και calloc() Και οι δύο διατηρούν μνήμη σωρού, αλλά διαφέρουν στα ορίσματά τους και στον τρόπο που χειρίζονται το νέο μπλοκ. Η malloc() δέχεται ένα όρισμα, τον συνολικό αριθμό bytes, και αφήνει τα περιεχόμενα χωρίς αρχικοποίηση, επομένως το μπλοκ διατηρεί απρόβλεπτες τιμές άχρηστων στοιχείων μέχρι το πρόγραμμα να γράψει σε αυτό. Η calloc() δέχεται δύο ορίσματα, τον αριθμό των στοιχείων και το μέγεθος του καθενός, και μηδενίζει κάθε byte πριν επιστρέψει τον δείκτη.
Οι πρακτικές διαφορές συνοψίζονται σε τρία σημεία:
- Αρχικοποίηση: η calloc() μηδενίζει τη μνήμη, ενώ η malloc() όχι, γεγονός που καθιστά την malloc() ελαφρώς ταχύτερη όταν οι τιμές θα αντικατασταθούν ούτως ή άλλως.
- Ορίσματα: γράφετε malloc(n * size) αλλά calloc(n, size) για να δεσμεύσετε τον ίδιο πίνακα.
- Περίπτωση χρήσης: επιλέξτε calloc() όταν έχει σημασία ένα καθαρό, μηδενισμένο μπλοκ και malloc() όταν προτιμάται η ταχύτητα και η αρχικοποίηση γίνεται χειροκίνητα.
Και οι δύο συναρτήσεις δηλώνονται στο stdlib.h, και οι δύο επιστρέφουν έναν δείκτη void ή NULL σε περίπτωση αποτυχίας και και οι δύο επιστρέφουν τη μνήμη τους με την ίδια συνάρτηση free().

