thomason993 Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Όταν δεσμεύω μνήμη με malloc στη C, ξέρω οτι μετά για να την απελευθερώσω όταν πλέον δε τη χρειάζομαι χρησιμοποιώ τη free. Π.χ. για να δεσμεύσω χώρο για ένα string: char * str = (char *)malloc(10); Και για να το αποδεσμεύσω: free(str); Όταν όμως δεσμεύω χώρο για ένα πίνακα από strings κάπως έτσι: char ** str_t = (char **)malloc(sizeof(char *)*10); και σε κάθε μία θέση του str_t δεσμεύσω χώρο για κάποιο string: str_t[0] = (char *)malloc(10); str_t[1] = (char *)malloc(10); ... κτλ. Μετά για να αποδεσμεύσω όλη τη μνήμη που έχω δεσμεύσει πρέπει να κάνω κάτι τέτοιο: free(str_t[0]); free(str_t[1]); . . . free(str_t[9]); free(str_t); ή και με μία εντολή free(str_t); έχω ξεμπερδέψει? Μήπως στη δεύτερη περίπτωση δημιουργείται memory leak?
ggeo1 Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Γενικά , για κάθε malloc που κάνεις χρειάζεσαι και ένα free. Όμως,εξαρτάται πως θα δεσμεύσεις τη μνήμη γι αυτό κοίτα και εδώ: http://stackoverflow.com/questions/12119692/how-to-free-double-pointers-after-usage-in-c http://stackoverflow.com/questions/11015360/free-a-double-pointer http://stackoverflow.com/questions/11854718/correct-way-to-free-double-pointers Στην περίπτωσή σου πρέπει να χρησιμοποιήσεις ένα loop : for ( int i = 0; i < 10; i++ ) { free( str_t[ i ] ); } και μετά : free(str_t); 1
thomason993 Δημοσ. 29 Νοεμβρίου 2015 Μέλος Δημοσ. 29 Νοεμβρίου 2015 Κατάλαβα.. και εγώ κάπως έτσι το είχα σκεφτεί, οτι θέλει δηλαδή μία free για κάθε malloc. Πολύ ξεκάθαρα τα παραδείγματα από stackoverflow, δεν είχα σκεφτεί να το ψάξω.. Ευχαριστώ!
groot Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Κατάλαβα.. και εγώ κάπως έτσι το είχα σκεφτεί, οτι θέλει δηλαδή μία free για κάθε malloc. Πολύ ξεκάθαρα τα παραδείγματα από stackoverflow, δεν είχα σκεφτεί να το ψάξω.. Ευχαριστώ! Καλός ο κανόνας "ένα free per malloc" αλλά το θέμα είναι να ξέρεις γιατί. Όταν έχεις **int (π.χ.) και κάνεις int** ppInt = (int**) malloc(sizeof(*int) * 10); και μετά: int indx; for (indx = 0; indx < 10; indx++) { ppint[indx] = (int*) malloc(sizeof(int) * 10); } έχεις έναν δείκτη σε δείκτη ακεραίου (ppint) και δείκτες σε ακέραιο. Άπαξ και σβήσεις τον ppint, πώς θα πας να βρεις που είναι οι δείκτες σε ακέραιο; Εάν είχες κάπου την διεύθυνση μνήμης τους, τότε μια χαρά θα μπορούσες να το κάνεις.
DDevil Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Χρησιμοποιησε την calloc καλυτερα για να αρχικοποιήσεις σε 0 την μνήμη που δεσμεύεις.
thomason993 Δημοσ. 29 Νοεμβρίου 2015 Μέλος Δημοσ. 29 Νοεμβρίου 2015 Εντάξει, μου λύθηκε αυτή η απορία. Αν τώρα για κάποιο λόγο, έχω πειράξει τον δέικτη που δείχνει στη δεσμευμένη μνήμη: Δηλ. να έχω αυτό: char * str = (char *)malloc(sizeof(char)*10); str++; Μετά πως πρέπει να κάνω την free() ?Έτσι: free(str); ή έτσι free(str-1); ?
the other one Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Ό,τι σου επέστρεψε η malloc αυτό περιμένει η free. Στην προκειμένη str-1. Αλλά για ευνόητους λόγους θα σου λεγα αυτούς τους pointer να μη τους πειράζεις. επίσης γενικά προσοχή με τα pointer arithmetics το p-1 είναι διαφορετκό αν το p είναι τύπου int* ή τύπου char* ας πούμε. Αυτά πάντως μπορείς να τα τεστάρεις και μόνος σου αν κάνεις λάθος free ας πουμε σου σκάει core dump.
DDevil Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Στα pointer arithmetics το p-1 είναι κανονικα p-1*sizeof(type) για τον μεταγλωτιστή.
defacer Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Κατάλαβα.. και εγώ κάπως έτσι το είχα σκεφτεί, οτι θέλει δηλαδή μία free για κάθε malloc. Πολύ ξεκάθαρα τα παραδείγματα από stackoverflow, δεν είχα σκεφτεί να το ψάξω.. Ευχαριστώ! BTW είναι επίσης καλό να μην κάνεις cast την επιστρεφόμενη τιμή της malloc. Δε θα επεκταθώ γιατί έχει συζητηθεί και εδώ στο forum και στο SO, μπορείς να ρίξεις ένα ψάξιμο για λεπτομέρειες. 1
DDevil Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Παντως αυτό που έκανε ο φιλος με τους δεικτες πιο πάνω και μετα έπρεπε να κάνει str-1 μεσα στην free δεν τ έχω ξαναδει. Επι τη ευκαιρια κοιταζα τον παρακάτω κώδικα αυτές τις μέρες για ένα δυναμικο string : #include<stdio.h> #include<sttdlib.h> #include<string.h> #define MAXINPUT 256+1 int main(void) { char input[MAXINPUT]={'\0'}; char *s=NULL; int maxlen=0; int len=0; do { printf("Give the len: "); fgets(input, MAXINPUT , stdin); maxlen= atoi(input); } while( maxlen < 1); maxlen++; s = calloc(maxlen, sizeof(char)); if( !s ) { fputs("Error", stderr); exit(EXIT_FAILURE); } printf("Give a string: "); fgets( s , maxlen , stdin); len =strlen(s); if( s[len-1] == '\n') s[len-1]= '\0'; printf("You gave: %s" , s); free(s); return 0; } Μεσα στο do ... while εγω μπορει να έβαζα και την scanf για να πάρει τον ακέραιο.... αλλα εδώ χρησιμοποιει την fgets για να πάρει την string αναπαράσταση του αριθμου και μετα να τον μετατρέψει με την atoi ωστοσο μου φαινεται περιεργο που το δευτερο ορισμα είναι 256+1 υπάρχει περιπτωση ποτε ο χρηστης να δωσει έναν αριθμο που έχει τοσους χαρακτήρες????
thomason993 Δημοσ. 29 Νοεμβρίου 2015 Μέλος Δημοσ. 29 Νοεμβρίου 2015 Ναι όντως, το str-1 είναι σωστό στη προκειμένη περίπτωση επειδή το sizeof(char) είναι 1. Ίσως το σωστό όπως είπε ο φίλος παραπάνω είναι ptr-1*sizeof(type). Όντως και σε μένα το πρόγραμμα "κρασάρει" μερικές φορές όταν κάνω free και μάλλον φταίει οτι δίνω λάθος θέση μνήμης στη free. Μεσα στο do ... while εγω μπορει να έβαζα και την scanf για να πάρει τον ακέραιο.... αλλα εδώ χρησιμοποιει την fgets για να πάρει την string αναπαράσταση του αριθμου και μετα να τον μετατρέψει με την atoi ωστοσο μου φαινεται περιεργο που το δευτερο ορισμα είναι 256+1 υπάρχει περιπτωση ποτε ο χρηστης να δωσει έναν αριθμο που έχει τοσους χαρακτήρες???? Προφανώς θέλει να καλύψει κάθε περίπτωση. Για να έχω πραγματικά δυναμική δέσμευση μνήμης πάντως, αυτό θεωρείται σωστό? char * buffer = malloc(sizeof(char)); char * temp, c; int i = 0; printf("Enter string:"); while ( (c=getchar()) !='\n'){ i++; temp = realloc(buffer,sizeof(char)*(i+1)); if(temp!=0){ buffer = temp; *(buffer+i-1)=c; } else{ printf("Realloc Error!\n"); free(buffer); _exit(1); } } *(buffer+i)='\0'; printf("You entered: '%s'\n",*buffer);
defacer Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 ωστοσο μου φαινεται περιεργο που το δευτερο ορισμα είναι 256+1 υπάρχει περιπτωση ποτε ο χρηστης να δωσει έναν αριθμο που έχει τοσους χαρακτήρες???? Όχι αν ο χρήστης είναι "βολικός" (δηλαδή: συμπεριφέρεται στο πρόγραμμα με το γάντι). Εξάλλου δεν έχει και νόημα αυτό γιατί όσο κι αν είναι το sizeof(int) σίγουρα δεν είναι αρκετά μεγάλο για να αναπαραστήσει καμια εκατοστή δεκαδικά ψηφία. Αν ο χρήστης δεν είναι βολικός (δηλαδή: από άγνοια ή από κακία κάνει "περίεργα πράγματα") τότε και πάλι δεν έχει νόημα αυτό γιατί μπορεί να σου δώσει 700 ψηφία το πρώτο input οπότε buffer overflow κλπ κλπ κλπ. Οπότε συνολικά, άσχετα τι υπάρχει περίπτωση να κάνει ο χρήστης το 256 + 1 δεν έχει κανένα νόημα. Για να έχω πραγματικά δυναμική δέσμευση μνήμης πάντως, αυτό θεωρείται σωστό? Με μια ματιά είναι σωστό, αλλά όχι πολύ καλογραμμένο (πολύ εύκολο να κάνεις λάθος κάπου εκεί). Επίσης, είναι λίγο καγκουριά και πάρα μα πάρα πολύ αργό το να κάνεις realloc σε κάθε χαρακτήρα σε σχέση με άλλες τεχνικές που χρησιμοποιούνται σε τέτοιες περιπτώσεις (βασικά, παραλλαγές πάνω στην ιδέα ότι πάντα κάνεις alloc παραπάνω μνήμη απ' όση χρειάζεσαι εκείνη τη στιγμή).
thomason993 Δημοσ. 29 Νοεμβρίου 2015 Μέλος Δημοσ. 29 Νοεμβρίου 2015 Με μια ματιά είναι σωστό, αλλά όχι πολύ καλογραμμένο (πολύ εύκολο να κάνεις λάθος κάπου εκεί). Επίσης, είναι λίγο καγκουριά και πάρα μα πάρα πολύ αργό το να κάνεις realloc σε κάθε χαρακτήρα σε σχέση με άλλες τεχνικές που χρησιμοποιούνται σε τέτοιες περιπτώσεις (βασικά, παραλλαγές πάνω στην ιδέα ότι πάντα κάνεις alloc παραπάνω μνήμη απ' όση χρειάζεσαι εκείνη τη στιγμή). Ωραία, τότε αυτό θα χρησιμοποιήσω και εγώ μιας και δε με πειράζει η ταχύτητα στη συγκεκριμένη περίπτωση. Από απορία όμως, πως μπορείς να επιταχύνεις αυτό το κώδικα? Από τη στιγμή που θα γίνει ο ίδιος αριθμός επαναλήψεων και στην επιλογή σου έχεις εντολές ίδιας λογικής (malloc, realloc, memcpy, memmove, κτλ) που φαντάζομαι έχουν και την ίδια ταχύτητα πάνω-κάτω, πώς μπορεί να γίνει πιο γρήγορα κάτι τέτοιο? Ή για να το επιταχύνεις πηγαίνεις σε προγραμματισμό χαμηλότερου επιπέδου?
defacer Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 Για να το επιταχύνεις δεν κάνεις realloc σε κάθε χαρακτήρα. Βέβαια, το να μιλάμε για ταχύτητα έχει πρακτικό νόημα μόνο αν το πρόγραμμα είναι CPU bound. Που εδώ δεν είναι, είναι I/O bound γιατί περιμένεις είσοδο από το χρήστη. 3
DDevil Δημοσ. 29 Νοεμβρίου 2015 Δημοσ. 29 Νοεμβρίου 2015 @defacer αμα ο χρηστης δώσει 700 ψηφια η fgets δεν θα κοψει το τελευταιο στον [255] και στον [256] θα θέσει το '\0'?? Επισης πως θα γινει υπερχειλιση αφου αυτος ο αριθμος δεν θα αποθηκευτεί σε μια μεταβλητή τύπου ακεραιου αλλα σε έναν πινακα χαρακτήρων συνολικού μεγέθους 257 χαρακτήρων. Παντως συνεχιζει να μου φαινεται κάπως αυτό εγω θα έβαζα ένα 9+1 το πολύ.Και όπως ειπα και πριν για μη μπλέκω με την atoi και επισης έναν πινακα που θελει έξτρα μνήμη θα έπαιζα με μια scanf μέσα στο do-while.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα