Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

καλημερα θα ηθελα να ρωτησω σε ποια περιπτωση πρεπει να κανω ξεχωριστα free καποιο πεδιο ενος struct ουτως ωστε να μην εχω memory leaks και σε ποια μπορω να κανω απλα free με το ονομα του struct μονο, γιατι εχω μπερδευτει λιγο, ευχαριστω πολυ εκ των προτερων!

Δημοσ.

Χωρίς να είμαι ειδικός, η απάντηση είναι ότι ελευθερώνεις ότι έχεις πάρει ήδη με malloc. Αν δίνεις σε ένα αλφαριθμητικό μια σταθερά τότε αυτή δεν θα γίνει free.

Δημοσ.

free θα κάνεις για κάθε malloc που έκανες. Δηλαδή στο τέλος θες να έχεις ίδιο αριθμό malloc-free.

 

Αν ένα struct έχει πεδία για τα οποία δέσμευσες μνήμη με malloc, τότε θα κάνεις και free γι'αυτά. Αν δέσμευσες δυναμικά μνήμη και για το struct, τότε free και γι'αυτό. Να είσαι προσεκτικός/ή και να κάνεις πάντα αποδέσμευση μνήμης από μέσα προς τα έξω. Γιατί;

#define NAME_LEN 20

struct name {
    char *first_name;
    char *last_name;
};

int main(void)
{
    struct name *name_1 = malloc(sizeof(struct name)); // εννοείται θέλουν ελέγχους
    name_1->first_name = malloc(NAME_LEN);
    name_1->last_name  = malloc(NAME_LEN);

    ...

    // free(name_1);  Τι θα συνέβαινε αν κάναμε εδώ free το name_1;
    free(name_1->first_name);
    free(name_1->last_name);
    free(name_1);

    return 0;
}

 

Δεν έχει τόσο προφανή απάντηση το ερώτημα που έθεσα.

 

Δημοσ.

..αν κανεις free τον δεικτη name_1 χωρις πρωτα να αποδεσμευσεις τα στοιχεια της δομης(first και last name), θα μεινει ξεμπαρκη δεσμευμενη μνημη στην οποια μετα δεν θα εχεις προσβαση..γι' αυτο, μην ξεχνας ΠΟΤΕ να αποδεσμευεις μνημη μετα απο καθε malloc..απο μεσα προς τα έξω οπως έγραψε ο gon.

Δημοσ.

..αν κανεις free τον δεικτη name_1 χωρις πρωτα να αποδεσμευσεις τα στοιχεια της δομης(first και last name), θα μεινει ξεμπαρκη δεσμευμενη μνημη στην οποια μετα δεν θα εχεις προσβαση..γι' αυτο, μην ξεχνας ΠΟΤΕ να αποδεσμευεις μνημη μετα απο καθε malloc..απο μεσα προς τα έξω οπως έγραψε ο gon.

Το πολύ αστείο είναι ότι μπορεί να μην έχεις πρόβλημα. Έτσι όπως το έχω γράψει είναι πολύ πιθανόν να δουλέψει.

 

Κανονικά ισχύει αυτό που είπες, ΑΛΛΑ, η free απλά μαρκάρει την περιοχή μνήμη που αναφέρεται, δεν τη μηδενίζει ή δεν κάνει invalidate τον pointer. Αυτό καταλήγει συνήθως σε segfaults, double free corruptions σε σημεία που για κανένα λόγο δεν περίμενες να συμβούν. Γι'αυτό μία ιδέα είναι, μετά από κάθε free, να κάνεις invalidation του pointer:

free(name_ptr);
name_ptr = NULL;

οπότε τουλάχιστον αν είναι να σου σκάσει θα ξέρεις που οφείλεται. Βοηθάει για το debugging πριν πας σε gdb.

  • Moderators
Δημοσ.

Να ρωτήσω κι εγώ κάτι. Γιατί να κάνεις free λίγο πριν τερματίσει το πρόγραμμά σου; Υποθέτωντας αυτά που κάνεις free τα χρησιμοποιεί μόνο το δικό σου πρόγραμμα (και δεν είναι, πχ, shared πράγματα με threads ή δεν ξέρω γω τι άλλο), ποιος ο λόγος να κάνεις free εκεί;

 

EDIT:

Γενικά μιλάω, όχι για το συγκεκριμένο παράδειγμα που έγραψες για να απαντήσεις στον OP.

Δημοσ.

ευχαριστω πολυ για τις απαντησεις, το χω καταλαβει σε θεωρητικο υποβαθρο αυτο που λετε... ας πουμε για παραδειγμα εχω ενα struct με τα εξης πεδια:

char *kleidi;
void * timi;
και ας πουμε οτι ονομαζεται p1. Θα ηταν καλυτερο να κανω σκετο free(p1), η να κανω πρωτα free(p1->kleidi); free(p1->timi); και μετα free(p1); η δεν παιζει καποιο ρολο καθως στα πεδια του δεν κανω καποια malloc?
Δημοσ.

αυτο που κανεις free και καπακι δινεις null τιμη στον pointer το διαβασα μολις χθες το βραδυ σε ενα βιβλιο. Βοηθαει για τον λογο που ειπες. καλο ειναι να υιοθετουνται τετοιες προγραμματιστικες συνηθειες.Topic starter μετα την δεσμευση να κανεις κι ελεγχο να δεις αν δεσμευθηκε η απαιτουμενη μνημη κι ολα πηγαν καλα!

Δημοσ.

Να ρωτήσω κι εγώ κάτι. Γιατί να κάνεις free λίγο πριν τερματίσει το πρόγραμμά σου; Υποθέτωντας αυτά που κάνεις free τα χρησιμοποιεί μόνο το δικό σου πρόγραμμα (και δεν είναι, πχ, shared πράγματα με threads ή δεν ξέρω γω τι άλλο), ποιος ο λόγος να κάνεις free εκεί;

 

EDIT:

Γενικά μιλάω, όχι για το συγκεκριμένο παράδειγμα που έγραψες για να απαντήσεις στον OP.

Στο συγκεκριμένο παράδειγμα έτυχε. Αποδέσμευση μνήμης μπορεί να κάνει όπου θέλει ο καθένας, αρκεί να μη χρειάζεται άλλο τα δεδομένα. Για παράδειγμα, χρησιμοποιώ μία δυναμική λίστα στην οποία αποθηκεύω κάποια πληροφορία από ένα αρχείο στην αρχή του προγράμματος. Στη συνέχεια, αφού τελειώσω με την επεξεργασία πληροφορίας και δε χρειάζομαι άλλο τη λίστα, μπορώ να την αποδεσμεύσω αν θέλω.

 

Συνήθως, για μικρές περιοχές μνήμης δε μας πολυ-ενδιαφέρει που θα τις αποδεσμεύσουμε. Για πολύ μεγάλες όμως, τότε είναι καλό να αποδεσμεύονται άμεσα, όταν παύουν αν είναι χρήσιμες καθώς μετά θα έρθουν κι άλλες και είναι σίγουρο ότι ο allocator δε θα βρίσκει χώρο να σου επιστρέψει. Εδώ μιλάω για εμένα. Δεν έχω διαβάσει κάποια καλή πρακτική για το πότε ακριβώς πρέπει.

 

 

ευχαριστω πολυ για τις απαντησεις, το χω καταλαβει σε θεωρητικο υποβαθρο αυτο που λετε... ας πουμε για παραδειγμα εχω ενα struct με τα εξης πεδια:

char *kleidi;
void * timi;
και ας πουμε οτι ονομαζεται p1. Θα ηταν καλυτερο να κανω σκετο free(p1), η να κανω πρωτα free(p1->kleidi); free(p1->timi); και μετα free(p1); η δεν παιζει καποιο ρολο καθως στα πεδια του δεν κανω καποια malloc?

 

Αν ξαναδιαβάσεις το μήνυμά μου θα καταλάβεις πως αν δεν κάνεις malloc, δεν κάνεις και free. Διαφορετικά, αν έχεις κάνει malloc, τότε δες παραπάνω το παράδειγμα.

  • Moderators
Δημοσ.

Εννοώ ότι όταν το πρόγραμμα τερματίσει, τη μνήμη θα την πάρει το OS έτσι κι αλλιώς. Οπότε, πέρα από συνήθεια-καλή γενικότερη πρακτική δεν υπάρχει λόγος να κάνεις free στο τέλος του προγράμματος, σωστά;

  • Like 1
Δημοσ.

Σχεδόν όλα τα μοντέρνα OS κάνουν αποδέσμευση μνήμης την οποία δεν έκανε free το προγραμμα, παρ´ όλα αυτά, το να μην κανείς free δεσμευμένη μνήμη ειναι κακή πρακτική γιατί:

 

• βασιζομενος σε behaviour ενός συγκεκρομενου OS αυτόματα μειώνεις το portability της λύσης σου

 

• Σκέψου τι συμβαίνει σε ενα μη ομαλό exit του προγράμματος όπως ενα ctrl-x.

 

• εάν θες να επεκτεινεις την λύση σου η να την ενσωματωσεις σε κάποια άλλη, τότε σε περιμένει memory leak bug hunt

Δημοσ.

Εννοώ ότι όταν το πρόγραμμα τερματίσει, τη μνήμη θα την πάρει το OS έτσι κι αλλιώς. Οπότε, πέρα από συνήθεια-καλή γενικότερη πρακτική δεν υπάρχει λόγος να κάνεις free στο τέλος του προγράμματος, σωστά;

Η αλήθεια είναι αυτό που είπε ο AlexHello, αλλά προσωπικά, προτιμώ να είμαι explicit σε ό,τι κάνω, οπότε για κάθε malloc θέλω και μία free. Υποτίθεται πως οι free αυξάνουν το χρόνο εκτέλεσης του προγράμματος, αλλά αν έχεις ένα μεγάλο πρόγραμμα, τότε πρέπει να κάνει free. Μεγάλα memory leaks σε ένα τέτοιο πρόγραμμα μόνο κακά μπορεί να προκαλέσουν.

Δημοσ.

Εννοώ ότι όταν το πρόγραμμα τερματίσει, τη μνήμη θα την πάρει το OS έτσι κι αλλιώς. Οπότε, πέρα από συνήθεια-καλή γενικότερη πρακτική δεν υπάρχει λόγος να κάνεις free στο τέλος του προγράμματος, σωστά;

 

Δεν υπάρχει "τεχνικός" λόγος να το κάνεις. Το θέμα είναι σε ποιά κατηγορία πέφτει το πρόγραμμά σου...

 

Άμα είναι άσχετη άσκηση για τη σχολή μη κάνεις και ποτέ free, δε θα αλλάξει τίποτα.

 

Σε ένα πιο mainstream πρόγραμμα που θα τρέξει για μη αμελητέο χρονικό διάστημα (ειδικά αν είναι server και θα τρέχει για πολύ καιρό) θέλει ευλαβικά malloc/free.

 

Αν φτάσεις στο άλλο άκρο και γράφεις π.χ. Redis που παίζει να φτάσεις uptime να μετριέται σε μήνες, memory usage σε GB και αριθμό allocations να μη χωράει σε int τότε ενδεχομένως υπάρχει λόγος να μη κάνεις επίτηδες free κατά τον τερματισμό του προγράμματος -- θα είναι που θα είναι τζάμπα δουλειά, υπό τέτοιες συνθήκες μπορεί κιόλας να πάρει πολλή ώρα.

 

Το πρόβλημα μ' αυτό το σενάριο είναι πως είναι το πιο περίπλοκο να υλοποιηθεί σωστά και εκτός των άλλων θα πρέπει να είναι και configurable. Αυτό διότι κατά τη διάρκεια του development θα θέλεις να έχεις memory leak detection και προφανώς αν δεν καθαρίζεις στο τέλος αυτό δεν είναι εφαρμόσιμο.

 

Αρθράκι Raymond Chen που απαντάει ακριβώς σ' αυτή την απορία: https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683

  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...