zztop845 Δημοσ. 26 Οκτωβρίου 2009 Δημοσ. 26 Οκτωβρίου 2009 Μερικές φορές στον προγραμματισμό παρουσιάζονται προβλήματα από εκεί που δεν το περιμένεις. Φτιάχνω ένα πρόγραμμα από χόμπι σε Visual C++ MFC. Στο πρόγραμμα δεσμεύω μνήμη μέσα από συνάρτηση μίας κλάσης. Το πρόβλημα είναι ότι αυτή η μνήμη δεν αποδεσμεύεται όταν καταργείται η κλάση που είναι τοπική μεταβλητή σε συνάρτηση. Για να είμαι πιο κατανοητός έγραψα σε C++ ένα αντίστοιχο πρόγραμμα. >#include <iostream> class sinartisis { public: class dedomena { public: int* d; int arithmos_dedomenon; dedomena() { arithmos_dedomenon = 0; } ~dedomena() { delete d; } void epektasi_mnimis(int x) { arithmos_dedomenon = x; d = new int [x]; for(int a=0;a<x;a++) d[a]=x; } }; class epexergasia_dedomenon { public: void epexergasia(sinartisis::dedomena data, sinartisis::dedomena* data_meta_apo_epexergasia) //Όχι ακριβώς επεξεργασία { int k; //Μία υποτυπώδης επεξεργασία k=2*data.arithmos_dedomenon+1; data_meta_apo_epexergasia->epektasi_mnimis(k); for(int x=0;x<data.arithmos_dedomenon;x++) data_meta_apo_epexergasia->d[x] = data.d[x]; } }; }; int main() { { sinartisis::dedomena data; sinartisis::dedomena data_meta_apo_epexergasia; sinartisis::epexergasia_dedomenon epex; data.epektasi_mnimis(2); //Γράφω πέντε πράγματα system("PAUSE"); for(int x=0;x<200000;x++) //Αντι για OnMouseMouve epex.epexergasia(data,&data_meta_apo_epexergasia); //Αντιγραφή } system("PAUSE"); return 1; } Εκτελέσετε το πρόγραμα σε όποιο μεταγλωττιστή θέλετε Πρίν πατήσετε το πρώτο system("PAUSE"); διαβάστε τη μνήμη (alt+ctrl+del) που καταλαμβάνει το πρόγραμμα. Μετά το δεύτερο system("PAUSE"); ξαναδιαβάστε την μνήμη. Κάθε φορά που γίνεται αντιγραφή η μνήμη παραμένει. Όταν το πρόγραμμα τερματίσει βέβαια το λειτουργικό αναλαμβάνει δράση και την αποδεσμεύει. Μπορεί να είναι κάτι απλό αλλά δεν είμαι και κάνας έμπειρος προγραμματιστής. Περιμένω τα φώτα σας.
m1cRo Δημοσ. 26 Οκτωβρίου 2009 Δημοσ. 26 Οκτωβρίου 2009 void epektasi_mnimis(int x) { arithmos_dedomenon = x; if(d!=NULL){ delete [] d; } d = new int [x]; for(int a=0;a<x;a++) d[a]=x; } Γενικός έχεις πολλά λάθη στον κώδικα αλλα dax αφού το κανεις από χόμπι ok.
zztop845 Δημοσ. 26 Οκτωβρίου 2009 Μέλος Δημοσ. 26 Οκτωβρίου 2009 Το if(d!=NULL){ delete [] d; } θα το βάλω ΟΚ. Ποια είναι τα υπόλοιπα λάθη; Ευχαριστώ.
bxenos Δημοσ. 26 Οκτωβρίου 2009 Δημοσ. 26 Οκτωβρίου 2009 >#include <iostream> class sinartisis { public: class dedomena { public: int* d; int arithmos_dedomenon; dedomena() { arithmos_dedomenon = 0; [color="Red"]//εδω δεν νομίζεις ότι πρέπει να δωσεις αρχική τιμή στο d; π.χ. d = NULL;[/color] } ~dedomena() { delete d; [color="#ff0000"]//είναι πίνακας, αρα delete []d; Το if(d!=NULL) είναι περιττό στη c++ για το delete[/color] } void epektasi_mnimis(int x) { arithmos_dedomenon = x; d = new int [x];[color="#ff0000"]//ελευθέρωσες τον πιθανα δεσμευμένο χωρο της d[] πρίν δεσμεύσεις καινούργιο;[/color] for(int a=0;a<x;a++) d[a]=x;[color="#ff0000"]//εδω δεν καταλαβαίνω το σκοπό σου αλλα δεν έχει σημασια[/color] } }; class epexergasia_dedomenon { public: void epexergasia(sinartisis::dedomena data, sinartisis::dedomena* data_meta_apo_epexergasia) //Όχι ακριβώς επεξεργασία { int k; //Μία υποτυπώδης επεξεργασία k=2*data.arithmos_dedomenon+1; data_meta_apo_epexergasia->epektasi_mnimis(k); for(int x=0;x<data.arithmos_dedomenon;x++) data_meta_apo_epexergasia->d[x] = data.d[x]; } }; }; int main() { { sinartisis::dedomena data; sinartisis::dedomena data_meta_apo_epexergasia; sinartisis::epexergasia_dedomenon epex; data.epektasi_mnimis(2); //Γράφω πέντε πράγματα system("PAUSE"); for(int x=0;x<200000;x++) //Αντι για OnMouseMouve epex.epexergasia(data,&data_meta_apo_epexergasia); //Αντιγραφή } system("PAUSE"); return 1; } .......................
georgemarios Δημοσ. 27 Οκτωβρίου 2009 Δημοσ. 27 Οκτωβρίου 2009 όπως λέει και ο bxenos, στο >[color=#000000][color=#007700] [/color][color=#0000BB]void epektasi_mnimis[/color][color=#007700]([/color][color=#0000BB]int x[/color][color=#007700]) { [/color][color=#0000BB]arithmos_dedomenon [/color][color=#007700]= [/color][color=#0000BB]x[/color][color=#007700]; [/color][color=#0000BB]d [/color][color=#007700]= new [/color][color=#0000BB]int [/color][color=#007700][[/color][color=#0000BB]x[/color][color=#007700]]; for([/color][color=#0000BB]int a[/color][color=#007700]=[/color][color=#0000BB]0[/color][color=#007700];[/color][color=#0000BB]a[/color][color=#007700]<[/color][color=#0000BB]x[/color][color=#007700];[/color][color=#0000BB]a[/color][color=#007700]++) [/color][color=#0000BB]d[/color][color=#007700][[/color][color=#0000BB]a[/color][color=#007700]]=[/color][color=#0000BB]x[/color][color=#007700]; } [/color][/color] πρέπει να κανεις πρώτα delete[] το d πριν καλεσεις το new[] (τσεκαροντας πριν αν το d δεν ειναι NULL) Ετσι όπως το εκανες, μετα το λουπ, η data_meta_apo_epexergasia δημιούργησε 200000 πίνακες αλλα κατα τον τερματισμό εκανε delete μονο τη μια (αρα εχεις 199999 leaks!)
Evgenios1 Δημοσ. 27 Οκτωβρίου 2009 Δημοσ. 27 Οκτωβρίου 2009 (αρα εχεις 199999 leaks!) Δεν ειναι πολυ. Εξαλλου καθαριζει ο kernel.
zztop845 Δημοσ. 27 Οκτωβρίου 2009 Μέλος Δημοσ. 27 Οκτωβρίου 2009 Νόμιζα πως με την new όταν δεσμεύω μεγαλύτερη μνήμη από πριν δεν χρειάζεται η delete. Έκανα το δοκιμαστικό πρόγραμμα λιγο πιο περίπλοκο και αντι για int τωδα δεσμεύω μια δομή που περιέχει μια άλλη δομη. Σε αυτή την περρίπτωση γιατί παρουσιάζεται σφάλμα μνήμης;. >#include <iostream> class sinartisis { public: struct domi { int a; char c; }; struct domi1 { int a; domi c; }; class dedomena { public: int *d; domi1 *dm1; int arithmos_dedomenon; dedomena() { arithmos_dedomenon = 0; d=NULL; dm1=NULL; } ~dedomena() { delete [] d;delete [] dm1; } void epektasi_mnimis(int x) { arithmos_dedomenon = x; delete [] d; d = new int [x]; delete [] dm1; dm1 = new domi1 [x]; } }; class epexergasia_dedomenon { public: void epexergasia(sinartisis::dedomena data, sinartisis::dedomena* data_meta_apo_epexergasia) //Όχι ακριβώς επεξεργασία { int k; k=data.arithmos_dedomenon; data_meta_apo_epexergasia->epektasi_mnimis(k); } }; }; int main() { { sinartisis::dedomena data; sinartisis::dedomena data_meta_apo_epexergasia; sinartisis::epexergasia_dedomenon epex; data.epektasi_mnimis(2); //Γράφω πέντε πράγματα system("PAUSE"); for(int x=0;x<30;x++) //Αντι για OnMouseMouve epex.epexergasia(data,&data_meta_apo_epexergasia); //Αντιγραφή } system("PAUSE"); return 1; } Ελπίζω να μην γίνομαι κουραστικός
bxenos Δημοσ. 27 Οκτωβρίου 2009 Δημοσ. 27 Οκτωβρίου 2009 >#include <iostream> class sinartisis { public: struct domi { int a; char c; }; struct domi1 { int a; domi c; }; class dedomena { public: int *d; domi1 *dm1; int arithmos_dedomenon; dedomena() { arithmos_dedomenon = 0; d=NULL; dm1=NULL; } [color="Red"]ΣΩΣΤΑ ΔΗΜΙΟΥΡΓΕΙΣ ΤΟ ΑΝΤΙΚΕΙΜΕΝΟ, ΑΛΛΑ ΔΕΝ ΕΧΕΙΣ COPY CONSTRUCTOR ΟΠΟΤΕ ΔΕΝ ΠΡΕΠΕΙ ΝΑ ΚΑΝΕΙΣ ΑΝΤΙΓΡΑΦΟ ΤΟΥ ΑΝΤΙΚΕΙΜΕΝΟΥ ΓΙΑΤΙ ΘΑ ΕΧΕΙΣ ΣΥΟ ΑΝΤΙΓΡΑΦΑ ΕΝΑ ΜΕ ΣΩΣΤΕΣ ΘΕΣΕΙΣ ΜΝΗΜΗΣ ΚΑΙ ΕΝΑ ΜΕ ΛΑΘΟΣ[/color] ~dedomena() { delete [] d;delete [] dm1; } void epektasi_mnimis(int x) { arithmos_dedomenon = x; delete [] d; d = new int [x]; delete [] dm1; dm1 = new domi1 [x]; } }; class epexergasia_dedomenon { public: void epexergasia(sinartisis::dedomena data, sinartisis::dedomena* data_meta_apo_epexergasia) //Όχι ακριβώς επεξεργασία { int k; k=data.arithmos_dedomenon; data_meta_apo_epexergasia->epektasi_mnimis(k); } }; }; int main() { { sinartisis::dedomena data; sinartisis::dedomena data_meta_apo_epexergasia; sinartisis::epexergasia_dedomenon epex; data.epektasi_mnimis(2); //Γράφω πέντε πράγματα system("PAUSE"); for(int x=0;x<30;x++) //Αντι για OnMouseMouve epex.epexergasia(data,&data_meta_apo_epexergasia); //Αντιγραφή [color="Red"]Η ΣΥΝΑΡΤΗΣΗ epexergasia ΠΡΟΣΠΑΘΕΙ ΝΑ ΚΑΝΕΙ ΑΝΤΙΓΡΑΦΟ ΤΟΥ data ΚΑΙ ΟΠΩΣ ΕΙΠΑ ΔΕΝ ΕΧΕΙΣ copy constructor Κανε search για copy constructor [/color] } system("PAUSE"); return 1; } Ελπίζω να μην γίνομαι κουραστικός Μη σκας δεν είσαι κουραστικός
zztop845 Δημοσ. 28 Οκτωβρίου 2009 Μέλος Δημοσ. 28 Οκτωβρίου 2009 Κατάλαβα. Ευχαριστώ για τις απαντήσεις.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.