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

Κλάσεις και σωρός στην C++


zztop845

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

Δημοσ.

Μερικές φορές στον προγραμματισμό παρουσιάζονται προβλήματα από εκεί που δεν το περιμένεις. Φτιάχνω ένα πρόγραμμα από χόμπι σε 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"); ξαναδιαβάστε την μνήμη. Κάθε φορά που γίνεται αντιγραφή η μνήμη παραμένει. Όταν το πρόγραμμα τερματίσει βέβαια το λειτουργικό αναλαμβάνει δράση και την αποδεσμεύει.

 

Μπορεί να είναι κάτι απλό αλλά δεν είμαι και κάνας έμπειρος προγραμματιστής. Περιμένω τα φώτα σας.

Δημοσ.

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.

Δημοσ.

>#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;
}

 

.......................

Δημοσ.

όπως λέει και ο 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!)

Δημοσ.

Νόμιζα πως με την 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;
}

 

Ελπίζω να μην γίνομαι κουραστικός :fear:

Δημοσ.

>#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;
}

 

Ελπίζω να μην γίνομαι κουραστικός :fear:

Μη σκας δεν είσαι κουραστικός

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...