Με την ευκαιρία, μιας που μιλάμε για c-strings, δεν ξέρω αν το έχει θίξει ο King, αλλά όλες οι έτοιμες συναρτήσεις διαχείρισης strings προκαλούν seg-fault αν το string τους περαστεί NULL.
Πρόκειται για μια συνειδητή επιλογή του σχεδιασμού της γλώσσας, στο βωμό της ταχύτητας εκτέλεσης. Το αντίτιμο είναι πως αν έστω και κατά λάθος περάσεις το string ως NULL σε οποιαδήποτε έτοιμη συνάρτηση, θα προκληθεί seg-fault. Κάτι παρόμοιο συμβαίνει και με τον μηδενικό χαρακτήρα, ο οποίος αν δεν υπάρχει, οι περισσότερες έτοιμες συναρτήσεις "προχωράνε" έξω από το όριο του μέγιστου μήκους που έχει οριστεί για το string (ορισμένες δέχονται το μέγιστο μήκος ως έξτρα όρισμα, αλλά και πάλι είναι ευθύνη του προγραμματιστή να περάσει σωστό νούμερο εκεί ... και όχι π.χ. μεγαλύτερο).
Η 2η περίπτωση αντιμετωπίζεται με πολύπλοκο τρόπο, μιας και προϋποθέτει τη δημιουργία νέου τύπου (π.χ. String) που μπορεί να εξαρτάται ή όχι από την ύπαρξη μηδενικού χαρακτήρα, καθώς και μια συλλογή από συναρτήσεις που θα διαχειρίζονται strings του τύπου String, αντίστοιχες των έτοιμων, αλλά πιο ασφαλείς (αυτό ονομάζεται managed approach).
Η 1η περίπτωση όμως αντιμετωπίζεται πολύ εύκολα, με έναν εσωτερικό έλεγχο στην κάθε μας συνάρτηση, για το αν το string που της περνάμε είναι ή όχι NULL (το λεγόμενο "sanity check"). Αν είναι NULL, τότε πολύ απλά σηματοδοτούμε με κάποιον τρόπο το σφάλμα κι επιστρέφουμε άπραγοι από την συνάρτηση.
Π.χ. η συνάρτηση που "κεφαλοποιεί" όλα τα γράμματα ενός string...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
char *s_toupper( char *s )
{
char *cp = s;
/* sanity check */
if ( !s )
return NULL;
while ( (*cp = (char)toupper( (int)(*cp) )) )
cp++;
return s;
}
Και όταν την καλούμε...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
...
if ( NULL == s_toupper( string ) ) {
/* internal *error */
...
}
...