Δημοσιεύτηκε: 05 Σεπ 2011, 09:03
Καλημέρα,
Θα μπορούσε, με την έννοια πως ο compiler δεν θα παραπονιόταν, αλλά όταν έτρεχες το πρόγραμμα θα έδινε segmentation fault στο συγκεκριμένο σημείο.
Είναι δηλαδή δική σου ευθύνη να εξασφαλίσεις είτε ότι δεν θα ζητήσεις να διαβάσεις από την κύρια είσοδο το παραπάνω string, είτε πως αν το ζητήσεις τότε να έχεις εξασφαλίσει πως το έχεις ορίσει να χωράει τουλάχιστον το ελάχιστο πλήθος χαρακτήρων + τον μηδενικό για τις ανάγκες του προγράμματος σε εκείνο το σημείο.
Στον 9ο χαρακτήρα ( username[8] ) πρέπει να έχει το '\0' ώστε να σηματοδοτείται το τέλος του τρέχοντος μήκους του και στη συνέχεια μέχρι και τον χαρακτήρα username[31] μπορεί να έχει οτιδήποτε ... ιδανικά όλο μηδενικούς χαρακτήρες.
Το buffer σου στο συγκεκριμένο παράδειγμα είναι 32 συνεχόμενα bytes στη μνήμη (32 χαρακτήρες) οπότε όσο αναφέρεσαι σε αυτό μένοντας εντός ορίων του δεν έχεις υπερχείλιση (ούτε άνω, ούτε κάτω).
Ίσως είχες διαβάσει κάτι άλλο, ή με άλλα συμφραζόμενα, δεν ξέρω. Ίσως διάβασες πως αν δεν γεμίσεις ότι περισσεύει μέχρι τον 32ο χαρακτήρα με '\0' τότε ρισκάρεις σε εκείνο τον χώρο να βάλουν χάκερς δικό τους κώδικα
Για αυτό και όταν ορίζετε strings να τα αρχικοποιείται ΠΑΝΤΑ με μηδενικούς χαρακτήρες σε όλο το μέγιστο μήκος τους!
Αν τα δηλώνετε ως πίνακες, αυτό γίνεται έτσι:
Ενώ αν τα δηλώνετε με χρήση δείκτη, τότε να δεσμεύετε τη μνήμη τους με calloc() αντί για malloc() ...
Χοντρικά, και μόνο για τα strings μιας και κάθε στοιχείο τους είναι 1 byte (1 χαρακτήρας) τρέχον μήκος είναι η τιμή που επιστρέφει η strlen( s ) και μέγιστο μήκος είναι η τιμή που επιστρέφει η sizeof( s ) (με την προϋπόθεση πως το s έχει οριστεί ως string και όχι ως string literal).
Ακριβώς!
Κι αυτό είναι κάτι που ισχύει για όλους τους πίνακες στη C και όχι μόνο για τα strings.
Σε high-level γλώσσες (π.χ. python) δεν θέλει τόσο ψείρισμα, γιατί εκείνες σου δίνουν έτοιμα πάρα πολλά πράγματα.
Π.χ.στη C++ εκτός από τον κλασικό τρόπο διαχείρισης των strings για τον οποίο συζητάμε εδώ, μπορείς εναλλακτικά να χρησιμοποιήσεις την κλάση string από στην στάνταρ βιβλιοθήκη της γλώσσας, οπότε όχι μόνο παύουν να σε απασχολούν τέτοιου είδους θέματα (τα τι & πως δηλαδή που συμβαίνουν στο παρασκήνιο), αλλά έχεις έτοιμη και μια διευρυμένη γκάμα από συναρτήσεις, τελεστές και δομές για τη διαχείριση των strings. Σε low-level γλώσσες όπως η C τέτοια λειτουργικότητα είτε πρέπει να την χτίσεις μόνος σου, είτε να τη βρεις έτοιμη αλλά σε ΜΗ στάνταρ βιβλιοθήκες (για τη C σχεδόν τα πάντα υπάρχουν έτοιμα, αλλά σε ΜΗ στάνταρ βιβλιοθήκες.... όπως π.χ. η μαθηματική βιβλιοθήκη mpfr που λέγαμε προχτές
)
Star_Light έγραψε:
...
1.οταν
λεω εισοδο απο τον χρηστη εννοω μεσω της fgets που έχουμε κανει παλαιοτερα. ΑΥτο εννοω. Δηλαδη τοδεν θα μπορούσε με μια fgets να περιμένει είσοδο απο τον χρήστη έτσι?
- Κώδικας: Επιλογή όλων
char s[]="";
Θα μπορούσε, με την έννοια πως ο compiler δεν θα παραπονιόταν, αλλά όταν έτρεχες το πρόγραμμα θα έδινε segmentation fault στο συγκεκριμένο σημείο.
Είναι δηλαδή δική σου ευθύνη να εξασφαλίσεις είτε ότι δεν θα ζητήσεις να διαβάσεις από την κύρια είσοδο το παραπάνω string, είτε πως αν το ζητήσεις τότε να έχεις εξασφαλίσει πως το έχεις ορίσει να χωράει τουλάχιστον το ελάχιστο πλήθος χαρακτήρων + τον μηδενικό για τις ανάγκες του προγράμματος σε εκείνο το σημείο.
έγραψε:
2.Οσο για αυτο που ειπα με το buffer overflow και τους 8 χαρακτήρες στο UNIX εννοουσα ονόματα χρηστών. Οχι ονοματα αρχείων ο
- Κώδικας: Επιλογή όλων
char username[32];
ειναι πίνακας για τα ονοματα οποτε εφοσον επιτρεπει μεχρι 8 απο 8-32 τι γίνεται??? Και εκει ειναι που ειχα διαβασει για buffer overflow.
Κάνω λάθος πιστεύεις?
Στον 9ο χαρακτήρα ( username[8] ) πρέπει να έχει το '\0' ώστε να σηματοδοτείται το τέλος του τρέχοντος μήκους του και στη συνέχεια μέχρι και τον χαρακτήρα username[31] μπορεί να έχει οτιδήποτε ... ιδανικά όλο μηδενικούς χαρακτήρες.
Το buffer σου στο συγκεκριμένο παράδειγμα είναι 32 συνεχόμενα bytes στη μνήμη (32 χαρακτήρες) οπότε όσο αναφέρεσαι σε αυτό μένοντας εντός ορίων του δεν έχεις υπερχείλιση (ούτε άνω, ούτε κάτω).
Ίσως είχες διαβάσει κάτι άλλο, ή με άλλα συμφραζόμενα, δεν ξέρω. Ίσως διάβασες πως αν δεν γεμίσεις ότι περισσεύει μέχρι τον 32ο χαρακτήρα με '\0' τότε ρισκάρεις σε εκείνο τον χώρο να βάλουν χάκερς δικό τους κώδικα
Αν τα δηλώνετε ως πίνακες, αυτό γίνεται έτσι:
- Κώδικας: Επιλογή όλων
char s[99+1] = { '\0' };
Ενώ αν τα δηλώνετε με χρήση δείκτη, τότε να δεσμεύετε τη μνήμη τους με calloc() αντί για malloc() ...
- Κώδικας: Επιλογή όλων
char *s = NULL;
s = calloc( 99+1, sizeof( char ) );
...
free( s );
έγραψε:
3. Στην σελίδα 115 έχεις πει (εκει που λες οτι δεν υπάρχει ξεχωριστος τυπος δεδομενων στην γλωσσα C για τα strings για αυτο και χανεται λιγο η μπαλα) πως το τρέχον μήκος ενος string δεν ισούται απαραίτητα με το συνολικό μεγεθός του... εδω σαν να μπερδεύτηκα τι εννοεις μπορεις να δειξεις ενα παραδειγμα????
Χοντρικά, και μόνο για τα strings μιας και κάθε στοιχείο τους είναι 1 byte (1 χαρακτήρας) τρέχον μήκος είναι η τιμή που επιστρέφει η strlen( s ) και μέγιστο μήκος είναι η τιμή που επιστρέφει η sizeof( s ) (με την προϋπόθεση πως το s έχει οριστεί ως string και όχι ως string literal).
- Κώδικας: Επιλογή όλων
char s[10] = "abc"; // strlen( s ) = 3, sizeof( s ) = 10
έγραψε:migf1 έγραψε:
Αν συμφωνήσουμε όμως πως κατά βάση τα strings είναι πίνακες χαρακτήρων, τότε λέγοντας δείκτης σε string είναι σαν να λέμε δείκτης σε πίνακα χαρακτήρων. Μιλάμε δηλαδή για διπλό δείκτη και όχι για μονό
Αυτο το λες επειδη εχεις ηδη εναν δεικτη που δειχνει στον πίνακα αλλα και το ονομα του πίνακα μετα ειναι απο μονος του ένας δείκτης ο οποίος δείχνει στο 1ο στοιχείο ετσι? κ.ο.κ
Ακριβώς!
Κι αυτό είναι κάτι που ισχύει για όλους τους πίνακες στη C και όχι μόνο για τα strings.
έγραψε:
![]()
![]()
θελει τρελο διαβασμα ο προγραμματισμος τελικα... και οχι μονο διαβασμα απλο... να παρεις ενα βιβλιο της C και να πεις οκ ξεκιναω να διαβαζω αυτα που γραφει... θελει γενικα τρελο ψειρισμα !
Σε high-level γλώσσες (π.χ. python) δεν θέλει τόσο ψείρισμα, γιατί εκείνες σου δίνουν έτοιμα πάρα πολλά πράγματα.
Π.χ.στη C++ εκτός από τον κλασικό τρόπο διαχείρισης των strings για τον οποίο συζητάμε εδώ, μπορείς εναλλακτικά να χρησιμοποιήσεις την κλάση string από στην στάνταρ βιβλιοθήκη της γλώσσας, οπότε όχι μόνο παύουν να σε απασχολούν τέτοιου είδους θέματα (τα τι & πως δηλαδή που συμβαίνουν στο παρασκήνιο), αλλά έχεις έτοιμη και μια διευρυμένη γκάμα από συναρτήσεις, τελεστές και δομές για τη διαχείριση των strings. Σε low-level γλώσσες όπως η C τέτοια λειτουργικότητα είτε πρέπει να την χτίσεις μόνος σου, είτε να τη βρεις έτοιμη αλλά σε ΜΗ στάνταρ βιβλιοθήκες (για τη C σχεδόν τα πάντα υπάρχουν έτοιμα, αλλά σε ΜΗ στάνταρ βιβλιοθήκες.... όπως π.χ. η μαθηματική βιβλιοθήκη mpfr που λέγαμε προχτές