Δημοσιεύτηκε: 10 Σεπ 2011, 20:21
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(). Αυτή η πρακτική πρέπει να μας γίνει συνήθεια σε ΟΛΕΣ τις συναρτήσεις που δέχονται δείκτες ως ορίσματα!
Δηλαδη αρχικα αρχικοποιεις τον δείκτη του πίνακα στο NULL μετα του δεσμευεις μνημη με malloc και μετα γεμιζεις μνημη με την memset σε αυτον? Γεμιζεις δηλαδη μνημη για το -1?
Βασικα νομιζω κανεις κατι αλλο.... θέτεις ολη την μνημη σε -1 και οσα εισαγει ο χρηστης γραφονται κανονικα... στις θεσεις οσα εχουν μεινει θεωρουμε πως τα αφησε κενα οποτε και φερουν απο πριν την τιμη -1 ?