Directx Δημοσ. 28 Νοεμβρίου 2007 Δημοσ. 28 Νοεμβρίου 2007 EDIT: μα η δέσμευση μνήμης μέσα στη δεύτερη for γίνεται μια φορά για κάθε i μέσα στο array. H πρώτη for αν κατάλαβα καλά είναι ανούσια επειδή δεσμεύεται 10 φορές το ίδιο πράγμα σε διαφορετική θέση μνήμης; Ναι - και δεν κρατάς μάλιστα αυτές τις διευθύνσεις παρά την τελευταία οπότε ούτε να τις αποδεσμεύσεις μπορείς (χαμένα μπλοκς) ... Τώρα γιατί αυτός ο κώδικας .. πάει κάπου το μυαλό μου αλλά είναι πολύ τολμηρό ...
Lomar Δημοσ. 28 Νοεμβρίου 2007 Μέλος Δημοσ. 28 Νοεμβρίου 2007 λέγε, λέγε! πες μου μπας και καταλάβω τι παίζει με τους καθηγητές μου
Directx Δημοσ. 28 Νοεμβρίου 2007 Δημοσ. 28 Νοεμβρίου 2007 Κοίταξε πιστεύω πως.. Δεσμεύει μικρά κομμάτια μνήμης θεωρώντας πως κάθε ένα από αυτά θα έχει την διεύθυνση του δίπλα στο άλλο. Ως πρακτική είναι τολμηρή διότι ποτέ δεν είμαστε σίγουροι για το τι διεύθυνση θα επιστρέψει η malloc όμως. Αυτό πρέπει να είναι το τρικ. Υ.Γ. Κρίμα που δεν συμμετέχει ενεργά ένας παλιός user του forum και master/professor στην C, θα ήθελα πολύ να άκουγα την γνώμη του για τον κώδικα του καθηγητή σου.. EDIT: Σε Borland/CodeGear C/C++ Builder 6.0 ο παρακάτω κώδικας κάνει free αυτά τα συνεχόμενα memory blocks, αποδυκνύοντας πως αυτή πρέπει να είναι η σκέψη του καθηγητού σας. Η τιμή 44 (που αφαιρείται από την τελευταία γνωστή διεύθυνση) προέρχεται από μελέτη του process memory map, σε σχέση με την απόσταση κάθε νέου malloc, κανονικά θα έπρεπε να είναι 40 αλλά υφίσταται 4-byte alignment. Φυσικά ο κώδικας αυτός δεν πιστεύω ότι θα λειτουργήσει σε άλλο περιβάλλον, καθώς και το default alignment μπορεί να διαφέρει και η malloc δεν είναι σίγουρο ότι θα επιστρέφει γραμμικές διευθύνσεις μνήμης. Η εξέταση των memory blocks έγινε με την βοήθεια του ενσωματωμένου στο C/C++ Builder, memory-checker CodeGuard και της printf("%p") .. > #include <stdio.h> #include <stdlib.h> int main(void) { int i,j; int **varray; for(i=0;i<10;i++) varray=(int **)malloc(10*sizeof(int)); for(i=0;i<44*10;i+=44) free((void*)((*(int*)&varray)-i)); return 0; } Αυτά από εμένα. Καλή συνέχεια!
alkisg Δημοσ. 28 Νοεμβρίου 2007 Δημοσ. 28 Νοεμβρίου 2007 Βρε παιδιά μήπως υπάρχει μπλέξιμο; Μου φαίνεται ότι ο Lomar μιλάει για τον κώδικα του καθηγητή του ενώ ο DirectX μιλάει για τον κώδικα του Red_Phantom... Καμία σχέση, εκτός αν κατάλαβα λάθος. Κατά τα άλλα για το varray είναι όπως τα λέει ο DiAvOl.
Directx Δημοσ. 29 Νοεμβρίου 2007 Δημοσ. 29 Νοεμβρίου 2007 Ναι αρχικά έτσι φαινότανε, πως αφορούσε τον κώδικα του Red_Phantom, αλλά μετά.. δεν ξέρω αλλάξανε τα πράγματα - το μόνο που ξέρω είναι πως κατά τον Lomar: Τον παραπάνω κώδικα τον έχει γράψει καθηγητής και μας τον έδωσε στο αντίστοιχο εργαστήριο το οποίο και έχω αύριο και απ'ότι φαίνεται θα τα ακούσει καλα! και ο παραπάνω κώδικας στην παρούσα σελίδα είναι αυτός που κάνει παράθεση από τον Red_Phantom ο φίλος DiAvOl: for(i=0;i<10;i++) varray=(int **)malloc(10*sizeof(int)); Και άντε πες ότι είμαι ξεκούτης φίλε Alkisg .. και τα μπέρδεψα αλλά πάει πολύ να με ρωτά για αυτό τον κώδικα λέγοντας .. λέγε, λέγε! πες μου μπας και καταλάβω τι παίζει με τους καθηγητές μου. Μάλιστα είναι ξεκάθαρο πως αφορά τον παρατιθέμενο κώδικα του DiAvOl καθώς ο Lomar σημειώνει: H πρώτη for αν κατάλαβα καλά είναι ανούσια επειδή δεσμεύεται 10 φορές το ίδιο πράγμα σε διαφορετική θέση μνήμης; Τώρα από εκεί και πέρα Άλκη μου .. εγώ τι να υποθέσω; ότι άλλον κώδικα βλέπει παραπάνω σε αυτή την σελίδα ο φίλος Lomar, αλλά .. άλλον εννοεί; και για άλλον διαφωνεί πως δουλεύει; και ύστερα ρωτά το πως & γιατί δουλεύει; (τότε ΧΑΙΡΕΤΑ μου τον πλάτανο!!!!) .. φυσικά στην 1 σελίδα είδα τον κώδικα του Red_Phantom, όμως μετά .. μπλέχτηκε το ζήτημα .. οπότε ... ... βρείτε τα μόνοι σας! Η ΟΥΣΙΑ που πρέπει να κρατήσει κανείς είναι πως ο κώδικας αυτός κάνει ένα ενδιαφέρον αλλά επικίνδυνο τρικ Αυτά.
alkisg Δημοσ. 29 Νοεμβρίου 2007 Δημοσ. 29 Νοεμβρίου 2007 Ε, δε νομίζω ότι λέγεται τρικ, λέγεται bug! 10 φορές malloc στον ίδιο pointer χωρίς free ανάμεσα είναι bug ανεξάρτητα από το τι κάνει παρακάτω.
Directx Δημοσ. 29 Νοεμβρίου 2007 Δημοσ. 29 Νοεμβρίου 2007 Γενικά, αυτή η τεχνική είναι κακός - bug prone κώδικας εκτός και αν έχουμε πάντα σειριακή δέσμευση μνήμης από το Λ.Σ. οπότε εκεί δεν λέγεται bug αλλά feature
Lomar Δημοσ. 29 Νοεμβρίου 2007 Μέλος Δημοσ. 29 Νοεμβρίου 2007 Directx για τον κώδικα που παρέθεσα στη πρώτη σελίδα μιλάω, αυτόν του καθηγητή... Πάντως σας ευχαριστώ όλους, σήμερα θα του το εξηγήσω το όνειρο του καθηγητή και περιμένω τις δικές του εξηγήσεις EDIT: Ρε παιδιά και εγώ μπερδεύτηκα, τελικα δν το έγραψε ο καθηγητής μου αυτό το for, ήταν παράδειγμα άλλου χρήστη... sorry για το mess up.
myle Δημοσ. 30 Νοεμβρίου 2007 Δημοσ. 30 Νοεμβρίου 2007 Ξεκάθαρα bug είναι. Σε καμία περίπτωση feature ανεξάρτητα από το πως δεσμεύεται η μνήμη (σειριακά ή όχι κάτι που δεν μπορεί να εγγυηθεί). Εκτός και αν ξέρετε κάποιο τρόπο να κάνετε free μετά την μνήμη για να μην υπάρχει memory leak. Προφανώς το παλικάρι που τον έκανε τον κώδικα εννούσε > varray = malloc(10*sizeof(int *)); for(i=0;i<10;i++) varray[i]=malloc(10*sizeof(int));
georgep800 Δημοσ. 6 Δεκεμβρίου 2007 Δημοσ. 6 Δεκεμβρίου 2007 Καλησπέρα! Προσπαθώ εδώ και αρκετή ώρα να δημιουργήσω μια διπλά συνδεμένη λίστα στην Java, χωρίς όμως αποτέλεσμα... Βρήκα ένα εγχειρίδιο που λέει πάνω κάτω τι χρειάζεται μια διπλά συνδεμένη λίστα και βάση αυτού δημιούργησα όλες της μεθόδους που απαιτούνται. Μήπως θέλει κάποιος να του στείλω το αρχείο με τον κώδικα που δημιούργησα, να μου δώσει μια μικρή υπόδειξη πως λειτουργεί.... Έχω μπερδευτεί λίγο...
Directx Δημοσ. 6 Δεκεμβρίου 2007 Δημοσ. 6 Δεκεμβρίου 2007 Ξεκάθαρα bug είναι. Σε καμία περίπτωση feature ανεξάρτητα από το πως δεσμεύεται η μνήμη (σειριακά ή όχι κάτι που δεν μπορεί να εγγυηθεί).Εκτός και αν ξέρετε κάποιο τρόπο να κάνετε free μετά την μνήμη για να μην υπάρχει memory leak. Προφανώς το παλικάρι που τον έκανε τον κώδικα εννούσε > varray = malloc(10*sizeof(int *)); for(i=0;i<10;i++) varray[i]=malloc(10*sizeof(int)); Αν το Λ.Σ. σου εγγυάται την σειριακή δέσμευση μνήμης από το πρώτο offset που δεσμεύεις τότε άκομψα (γιατί να μην αποθηκεύσεις την διεύθυνση σε ένα handle;) μπορείς να κάνεις αποδέσμευση μνήμης, με όλη την ταλαιπωρία που παρουσιάζει - σε κάθε άλλη περίπτωση υπάρχει πρόβλημα. Ο τρόπος που ανήρτησα (και ΠΡΟΣΟΧΗ δουλεύει υπό τις ακόλουθες πάντα προϋποθέσεις) αποδεσμεύει όλη την δεσμευμένη μνήμη υπό την προϋπόθεσή α) πως το malloc επιστρέφει σειριακές θέσεις και β) πως γνωρίζω το μέγεθος κάθε μπλοκ και το memory-alignment του compiler μου. Δεν λέω πως είναι σωστή τεχνική (είπα bug-prone) αλλά σε μια extreme περίπτωση την οποία διευκρίνισα (σειριακή δέσμευση) θα μπορούσε να λειτουργήσει (εξ' ου και ο χαρακτηρισμός τρικ) -ψάξτε τα παλία Λ.Σ. δεκαετία του '50 και '60 για την διαχείριση της μνήμης τους. Από εκεί και πέρα, νομίζω εξήγησα πέραν πάσης αμφιβολίας πως επειδή σήμερα το malloc ΔΕΝ ξέρουμε τι θέση θα μας επιστρέψει -ΔΕΝ προτιμούμε αυτή την τακτική διότι πέραν του ότι είναι άσχημη έχει πάψει και να δουλεύει δεκαετίες τώρα.- Αυτά, για να τελειώνουμε με το ΠΩΣ & ΓΙΑΤΙ - και καλή συνέχεια.
alkisg Δημοσ. 6 Δεκεμβρίου 2007 Δημοσ. 6 Δεκεμβρίου 2007 Δεν είναι δυνατόν σε καμία περίπτωση η malloc να εγγυάται σειριακή δέσμευση μνήμης. Αυτό επειδή χρησιμοποιείται heap οπότε μετά από κάποια malloc/free/malloc/free εγγυημένα υπάρχει κατακερματισμός. Σε οποιοδήποτε λειτουργικό και σε οποιαδήποτε libc. Αν ποτέ προσπαθούσαμε να φτιάξουμε έναν memory manager που θα εγγυούταν σειριακή malloc, τότε φαντάσου το παρακάτω σενάριο: κάνω malloc τα παρακάτω: A, B, C, D, E, F, G και θεωρώ ότι είναι τόσο μεγάλα που γεμίζει η μνήμη. Κάνω free το D οπότε αδειάζει η μνήμη στο μέσον της. Κάνω malloc το H. Θα έπρεπε να το βάλει μετά το G, αλλά δεν υπάρχει καν διαθέσιμο address space. Θα πρέπει να το βάλει εκεί που ήταν το D. Ακόμα κι αν θεωρήσουμε ότι μετακινούσε τα E, F, G αριστερότερα, και πάλι μου ακυρώνει τους pointers E, F, G και ακόμα το H δεν είναι σειριακά μετά το G, αλλά στην προηγούμενη θέση του. No way να μην είναι bug. Είναι το ίδιο σωστό με το να κάνω free(0x12345678); και να δουλεύει επειδή τυχαία μου έβαλε εκεί ο compiler μου την προηγούμενη malloc.
Directx Δημοσ. 6 Δεκεμβρίου 2007 Δημοσ. 6 Δεκεμβρίου 2007 Από εκεί και πέρα, νομίζω εξήγησα πέραν πάσης αμφιβολίας πως επειδή σήμερα το malloc ΔΕΝ ξέρουμε τι θέση θα μας επιστρέψει -ΔΕΝ προτιμούμε αυτή την τακτική διότι πέραν του ότι είναι άσχημη έχει πάψει και να δουλεύει δεκαετίες τώρα.-. Πόσο πιο καθαρά να το γράψω; Over and out.. Υ.Γ. 1. Να ψάξετε στην αρχαιότητα (1950-1960/64+-) ΠΩΣ κάνανε Memory Allocation (δοκιμάστε το, η WikiPedia είναι φίλη μας!) και τότε θα καταλάβετε γιατί το λέω άχρηστο πια bug-prone TRICK -και να κάνετε τον σταυρό σας που έχουμε Dynamic Memory allocation όσοι προγραμματίζεται! 2. Alkisg, ευχαριστώ για τα μαθήματα στο Memory Management αλλά δεν θεωρώ πως τα έχω ανάγκη εντούτοις να είσαι καλά. Και θερμή παράκληση, την επόμενη φορά να διαβάζεις καλύτερα όσα γράφω (είναι η δεύτερη φορά στο παρόν topic που παρεξηγείς, ελπίζω ακούσια (χμμμμ), τα γραφόμενα μου ...).
alkisg Δημοσ. 6 Δεκεμβρίου 2007 Δημοσ. 6 Δεκεμβρίου 2007 Μην παρεξηγιέσαι βρε, τόσα χρόνια εδώ μέσα έχει φανεί η αξία σου σαν προγραμματιστής. Και μόνο το ότι παρατήρησες ότι ο εν λόγω κώδικας μπορεί υπό προϋποθέσεις να δουλέψει σωστά είναι αξιέπαινο!!! Απλά απάντησα στο "υπό την προϋπόθεσή α) πως το malloc επιστρέφει σειριακές θέσεις" ότι είναι αδύνατο, κάποτε τελειώνει το address space. Άλλο να τύχει για 10 malloc στην αρχή της εκτέλεσης και άλλο να θεωρούμε ότι μπορεί να υπάρξει τέτοια υλοποίηση/προϋπόθεση. Μην τα παίρνεις χωρίς λόγο, προσωπικά τουλάχιστον από αυτά που γράφεις μου έχεις δώσει την εντύπωση ώριμου ατόμου και καλού προγραμματιστή, δεν είχα σκοπό να σε θίξω... Αλίμονο, είμαστε που είμαστε λίγοι οι codegear users, να κονταροχτυπιόμαστε και μεταξύ μας... Υ.Γ. δε νομίζω ότι παρεξήγησα (αλήθεια η πρώτη φορά ποια ήταν; δεν κατάλαβα), δεν είπα ότι το προτείνεις σαν τεχνική, είπα μόνο το ότι είναι αδύνατη η σειριακή malloc.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.