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

Απορία πάνω σε 2 κώδικες σε C++


babel47

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

Δημοσ.

Παιδιά έχω τους παρακάτω κώδικες:

 

># include <stdio.h>
# include <iostream>
void foo(int **n);
int main (void)
{
int dim1=3;
int *p=new int[dim1];
foo(&p);
delete p;
return 0;
}
void foo(int **n)
{
if (*n)
delete *n;
}

 

 

># include <stdio.h>
# include <iostream>
void foo(int *n);
int main (void)
{
int dim1=3;
int *p=new int[dim1];
foo(p);
return 0;
}
void foo(int *n)
{
if (n)
delete &n;
}

 

Καταλαβαίνω σε γενικές γραμμές τι κάνουν όμως δεν νομίζω πως έχω καταλάβει σε βάθος την διαφορά μεταξύ στις κλήσεις μεταξύ των 2 κωδίκων. Μπορεί κάποιος να βοηθήσει αναλύοντας πώς γίνεται η κλήση σε κάθε περίπτωση?

Δημοσ.

Στο πρώτο παράδειγμα η συνάρτηση foo παίρνει ώς όρισμα ένα δείκτη σε έναν δείκτη ενός ακεραίου (pointer to int pointer). Πρίν την καλέσει δημιουργεί έναν δείκτη σε ακέραιο και δεσμέυει την αντίστοιχη μνήμη: int *p=new int[dim1];. Μετά καλεί την συνάρτηση foo δίνωντας ώς όρισμα την διεύθυνση την μεταβλητής p που στην ουσία είναι ένας δείκτη σε έναν δείκτη ενός ακεραίου (pointer to int pointer) foo(&p);.

 

Στο δεύτερο παράδειγμα η συνάρτηση foo παίρνει ώς όρισμα έναν δείκτη σε ένα ακεραίου. Πρίν την καλέσει δημιουργεί έναν δείκτη σε ακέραιο και δεσμέυει την αντίστοιχη μνήμη: int *p=new int[dim1];. Μετά καλεί την συνάρτηση foo δίνωντας ώς όρισμα την p foo(p);.

Δημοσ.

Δηλαδή αν έχω καταλάβει καλά... η πρώτη κάνει κλήση με αναφορά ενώ η δεύτερη όχι? Μήπως είναι αυτός ο λόγος που κάνει delete &n στην δεύτερη ?

Δημοσ.

Το ξέρω φιλε babel οτι δεν είναι αυτή η ερώτηση αλλα

και οι 2 κώδικες ως έχουν προκαλούν seg fault.

 

Για την ακρίβεια ο πρώτος κάνει double free προσπαθεί να αποδεσμευσει την ίδια μνήμη 2 φορές και ο 2ος προσπαθεί να αποδεσμευσει μνήμη την οποία δεν έχει δεσμευσει.

Δημοσ.
Το ξέρω φιλε babel οτι δεν είναι αυτή η ερώτηση αλλα

και οι 2 κώδικες ως έχουν προκαλούν seg fault.

 

Για την ακρίβεια ο πρώτος κάνει double free προσπαθεί να αποδεσμευσει την ίδια μνήμη 2 φορές και ο 2ος προσπαθεί να αποδεσμευσει μνήμη την οποία δεν έχει δεσμευσει.

 

+1 :)))))))

Δημοσ.

Με dev-C++ που τους τρεχω εγω (console application) δεν μου βγαζουν ερρορ κατα το running στην κονσόλα. Εσεις με ποιο προγραμμα τους τρεχετε?

Δημοσ.

το οτι δε σου χτυπαει ερρορ δε σημαινει πως δεν υπαρχει ερρορ. Υπαρχει. Και στα 2. Εχει δικιο ο kathas

 

στο πρωτο

...

int main (void)

{

int dim1=3;

int *p=new int[dim1];

foo(&p);

delete p; // 2ο delete

return 0;

}

 

void foo(int **n)

{

if (*n)

delete *n; // 1o delete

}

τα κοκκινα κανουν το ιδιο πραγμα διαδοχικα, τη πρωτη φορα θα κανει delete και τη δευτερη ειναι boom! γιατι η μνημη ειναι ηδη αποδεσμευμενη

 

στο 2ο

if (n)

delete &n; //boom! (επρεπε να ειναι delete n (χωρις το &)

delete n σημαινει αποδεσμευσε τη θεση μνημη στην οποια δειχνει ο δεικτης n

delete &n σημαινει αποδεσμευσε τη θεση μνημης στην οποια βρισκεται ο ιδιος ο ποιντερ :whistle: στην οποια ουτως ή αλλως δεν εχεις προσβαση γιατι δεν την δεσμευσες εσυ (στο λεω μπακαλιστικα λιγο, μη με παρετε με τις πετρες οι υπολοιποι)

Δημοσ.

Α μαλιστα , για το πρωτο που λες εχω καταλαβει κανει το ιδιο πραγμα 2 φορες...

 

Τωρα για το δευτερο αν εχω καταλαβει καλα, το delete &n θελει να αποδεσμευσει οχι την θεση που δειχνει ο pointer n αλλα την διευθυνση του pointer... Εκτος του οτι δεν εχω εγω προσβαση σε αυτην την διευθυνση που ειναι το λαθος? Δεν υπαρχει περιπτωση να θελω να αποδεσμευσω συτην την θεση μνημης? Και εφοσον δεν πεταει seg fault ...

Δημοσ.

ok, παρε φαση

 

κατ αρχην

Εκτος του οτι δεν εχω εγω προσβαση σε αυτην την διευθυνση που ειναι το λαθος?
το προφανες, το οτι εχεις βαλει ενα statement που περιμενεις να κανει κατι και αντι γιαυτο κανει κατι αλλο. Ακομα και αν αυτο το "αλλο" ειναι ακινδυνο (που δεν ειναι) σιγουρα δε κανει αυτο που ηθελες εσυ αρχικα, δηλ να αποδεσμευσεις το array που δημιουργησες πριν με το new int[dim1]

 

επειτα

int *p=new int[dim1];

εδω τι γινεται;

οριζεις το p ως μια μεταβλητη τυπου integer pointer. Το p στην ουσια δεν ειναι τιποτε παραπανω απο μια τοπικη μεταβλητη στην οποια καταχωρειται ενα νουμερο.

Τωρα, με το new int[dim1] λες στο μηχανημα να καβατζωσει μια ποσοτητα μνημης, ιση με dim1 X <μεγεθος του int>. Σε ενα 32bit συστημα, για dim1 = 10, θα ειναι 10Χ4=40bytes. Αυτη η ποσοτητα μνημης ειναι συνεχομενη και αρχιζει απο καποιο σημειο της μνημης το οποιο εχει ενα μοναδικο αριθμο, την "διευθυνση" της. Αυτη η διευθυνση καταχωρειται στο p, ωστε να μπορουμε να την βρισκουμε. Ετσι πχ, αν κατα λαθος μετα το int *p=new int[dim1]; γραψεις p=0; τοτε η μνημη του array που μολις δεσμευσες δε θα ειανι προσβασιμη απο κανενα και το συστημα θα πρεπει να κανει reboot για να την ανακτησει.

Ολα αυτα στα ειπα για να καταλαβεις μια βασικη διαφορα. Το p, ειναι ενας αριθμος που θελει απο μονος του μια μνημη (νομιζω ειναι οσο πιανει ενας integer αλλα μπορει να κανω λαθος, αναλογα το συστημα ισως). Εδω, το p ειναι τοπικη μεταβλητη, δημιουργειται στο stack και θα αποδεσμευτει μονο οταν βγει "out-of-scope" και εφοσον το ορισες μεσα στη main, out-of-scope σημαινει οταν τερματισει το προγραμμα. Η μνημη που δεσμευσες με την εντολη new ειναι διαφορετικη, δεσμευεται στο heap και ειναι αυθυνη του προγραμματιστη να την αποδεσμευσει με ενα delete οταν δεν την χρειαζεται πια. Λεγοντας λοιπον εσυ delete &p πας να αποδεσμευεις τη μνημη που βρισκεται ο p και οχι τη μνημη που δεσμευσες με τη new.

Αρα, διπλο λαθος. ΚΑΙ δεν αποδεσμευεις τη μνημη, ΚΑΙ κινδυνευεις να κρασαρεις καθως ειναι ετοιμορροπο το προγραμμα.

 

Αυτα και ελπιζω να μη σε ζαλισα.....

  • 2 εβδομάδες αργότερα...

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

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

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