Συντονιστής: konnn



migf1 έγραψε:Ελπίζοντας πως έχετε καταλάβει τα του προηγούμενου ποστ, πάμε να φτιάξουμε τις μέχρι τώρα συναρτήσεις μας να είναι πιο ασφαλείς !
Στην γραμμή 54 του κώδικά μας, στη main(), έχουμε προνοήσει και ελέγχουμε ώστε αν ο δείκτης table είναι NULL μετά το malloc() (επειδή π.χ. απέτυχε να δεσμευτεί μνήμη για αυτόν) να ειδοποιούμε τον χρήστη και να τερματίζουμε το πρόγραμμα).
Τι θα γινόταν όμως αν δεν κάναμε τον έλεγχο αυτόν και αφήναμε τη ροή να συνεχίσει; Για να δείτε τι θα γινόταν απενεργοποιήστε προσωρινά τη γραμμή του malloc() (για να είναι NULL ο table, λόγω της αρχικοποίησης στον ορισμό του) καθώς και τις γραμμές του ελέγχου μετά το malloc() και τρέξτε το πρόγραμμα. Για να απενεργοποιείτε στα γρήγορα συνεχόμενες γραμμές κώδικα, μπορείτε να χρησιμοποιείτε το pre-processor directive #if #endif, δηλαδή για το παραπάνω:
- Κώδικας: Επιλογή όλων
...
#if 0 // αλλάξτε το σε: #if 1 ή σβήστε το, μαζί με το #endif, για να ενεργοποιηθούν ξανά οι γραμμές
table = malloc( tabsize ); /* δέσμευση μνήμης για τον πίνακα */
if ( !table ) { /* αποτυχία δέσμευσης μνήμης */
puts("*** σφάλμα: ανεπαρκής μνήμη, τερματισμός προγράμματος..." );
exit( EXIT_FAILURE ); /* ... τερματισμός προγράμματος */
}
#endif
memset( table, EMPTYELEM, tabsize ); /* αρχικοποίηση όλων των στοιχείων */
...
Αυτό που θα γίνει είναι πως η memset() θα παράξει segmentation-fault ! Απενεργοποιήστε την κι αυτή προσωρινά, καθώς και το puts() που ακολουθεί για να παέι η ροή απευθείας στη γραμμή που καλεί τη συνάρτηση:
- Κώδικας: Επιλογή όλων
table_print_stats( table, maxelems, tabsize ); /* τύπωμα στατιστικών */
Θα διαπιστώσετε πως και αυτή θα παράξει segmentation-fault !
Η επόμενη άσκηση λοιπόν είναι να τροποποιήσετε τον κώδικα των συναρτήσεων: tablen(), table_print_stats() και table_print_contents() ώστε να μην παράγουν segmentation-fault όταν ο πίνακας είναι NULL.
Σκεφτείτε το σαν ένα 2ο επίπεδο ασφάλειας, σε περίπτωση που μας διαφύγει να κάνουμε τον σχετικό έλεγχο στη main(). Αυτή η πρακτική πρέπει να μας γίνει συνήθεια σε ΟΛΕΣ τις συναρτήσεις που δέχονται δείκτες ως ορίσματα!

// ορισμός της δομής struct point
struct point {
int x;
int y;
};
#include <stdio.h>
// ορισμός της δομής struct point
struct point {
int x;
int y;
};
/* ----------------------------------------------------------- */
int main( void )
{
struct point a, b; // ορισμός 2 σημείων a και b
...
a.x = 10;
a.y = 12;
b.x = 100;
b.y = 12;
...
struct point a;
a.x = 10;
#include <stdio.h>
// ορισμός της δομής struct point
struct point {
int x;
int y;
};
/* ----------------------------------------------------------- */
int main( void )
{
struct point *a = NULL; // ορισμός ενός σημείου a ως δείκτη σε δομή struct point
a = calloc(1, sizeof( struct point ) );
if ( !a ) {
// διαχειριστείτε εδώ ενδεχόμενη αποτυχία δέσμευση μνήμης για το a
}
a->x = 10;
a->y = 12;
...
if ( a )
free( a );
a = NULL;
}
return 0;
}
#include <stdio.h>
// ορισμός & κατοχύρωση της δομής struct point ως πρόσθετο τύπο δεδομένων με το όνομα Point
typedef struct point {
int x;
int y;
} Point;
/* ----------------------------------------------------------- */
int main( void )
{
Point *a = NULL; // ορισμός ενός σημείου a ως δείκτη σε δομή struct point
a = calloc(1, sizeof( Point ) );
if ( !a ) {
// διαχειριστείτε εδώ ενδεχόμενη αποτυχία δέσμευση μνήμης για το a
}
a->x = 10;
a->y = 12;
...
if ( a )
free( a );
a = NULL;
}
return 0;
}
draw_line( int ax, int ay, int bx, int by );
draw_line( Point a, Point b );

Star_Light έγραψε:
Δηλαδη αρχικα αρχικοποιεις τον δείκτη του πίνακα στο NULL μετα του δεσμευεις μνημη με malloc και μετα γεμιζεις μνημη με την memset σε αυτον?
έγραψε:
- Κώδικας: Επιλογή όλων
Γεμιζεις δηλαδη μνημη για το -1?
έγραψε:Βασικα νομιζω κανεις κατι αλλο.... θέτεις ολη την μνημη σε -1
έγραψε: και οσα εισαγει ο χρηστης γραφονται κανονικα... στις θεσεις οσα εχουν μεινει θεωρουμε πως τα αφησε κενα οποτε και φερουν απο πριν την τιμη -1 ?




migf1 έγραψε:χιχιχιχι... no problem, εγώ το κατάλαβα πάντως
Και για να προχωρήσουμε, η λύση της 2ης άσκησης είναι να βάλετε έναν έλεγχο πρόωρης εξόδου στις αρχές των συναρτήσεων, ώστε όταν το όρισμα του δείκτη table είναι NULL η συνάρτηση να επιστρέφει (χωρίς δηλαδή να επιχειρήσει να εξετάσει κανένα στοιχείο του πίνακα. Το έχω βάλει ήδη στην table_print_contents() στο ideone.com εγώ, βάλτε το και στις υπόλοιπες και δώστε μου το ΟΚ να το βάλω κι εγώ στις υπόλοιπες συναρτήσεις στο ideone.com.
ΥΓ. Μιας και είμαστε όλοι εδώ τώρα (γεια σου Γιώργο) δεν συνεχίζω με τις δομές μέχρι να τελειώσετε με τα προηγούμενα και να μου δώσετε το οκ
if(!table)
return;
