Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

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

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 04 Σεπ 2011, 19:56

Star_Light έγραψε:Λιγο πριν προχωρησουμε εχω κάποιες απορίες.

1.
Στο
Κώδικας: Επιλογή όλων
char s[100]="testing"


μπορει να δεχθεί άλλες 92 τιμές για είσοδο? Πχ απο τον χρήστη... (φυσικά απο τον δείκτη s[5] και μετα )

Ναι, 91 ωφέλιμους (κι έναν για το '\0'). Αυτό που με μπερδεύει στην ερώτησή σου είναι το "να δεχτεί κι άλλους χαρακτήρες από τον χρήστη". Και με μπερδεύει γιατί ο χρήστης μπορεί να γράψει στην κύρια είσοδο ότι του κατέβει στο κεφάλι, το θέμα είναι τι κάνει ο προγραμματιστής με τα δεδομένα που του δίνει ο χρήστης (ποια κρατάει, ποια πετάει, ποια αφήνει ίδια, ποια μετατρέπει σε αριθμούς, κλπ, κλπ).

έγραψε:Απο οσο εχω καταλαβει ενα string ειναι ενας πίνακας χαρακτήρων αλλα μπορω και με βεβαιότητα να πω (συμφωνα με αυτα που εδωσε και ο migf και τα διαβασα αρκετα καλα) οτι ενας πίνακας χαρακτήρων δεν ειναι απαραίτητα ενα string. Οκ?

Ακριβώς :)

έγραψε:
2. Κανονικα το
Κώδικας: Επιλογή όλων
char s[] = "";


δεν μπορει να περιμένει είσοδο απο τον χρήστη ή πρεπει να του ορίσεις μια τιμή στο μέγεθος (του πίνακα) ωστε να ξέρει ο μεταγλωττιστής απο ποιο σημείο και μετα θα πρεπει να βάλει τον μηδενικο χαρακτηρα ο οποιος και σηματοδοτει το τελος της συμβολοσειρας για να ελενξει με πιο σωστο τροπο την εισοδο του χρηστη?

Στον παραπάνω ορισμό το s περιέχει ήδη τον μηδενικό χαρακτήρα. Ο παραπάνω ορισμός είναι ισοδύναμος του:
Κώδικας: Επιλογή όλων
char s[1] = { '\0' );

Ελπίζω αυτό να απαντάει την ερώτηση (επίσης πάλι δεν καταλαβαίνω τι εννοείς όταν λες "να περιμένει είσοδο από το χρήστη"... ποιος να περιμένει είσοδο από το χρήστη; )

έγραψε:
Και τελος αν

3.
Κώδικας: Επιλογή όλων
char usernme[32];

Αν δηλωσεις δηλαδη εναν πίνακα με στοιχεια παραπανω απο οσα χρειάζεσαι (επειδη πχ το UNIX επιτρέπει μεχρι 8 χαρακτήρες ονοματα) τοτε εδω μπορει να γινει ας πουμε buffer overflow?
:D

Overflow (άνω υπερχείλιση) έχουμε όταν εσύ ως προγραμματιστής συνειδητά ή κατά λάθος προσπαθείς να διαχειριστείς κάποιο στοιχείο που βρίσκεται μετά το τέλος του οποιουδήποτε πίνακά σου, της δομής σου, κλπ. Underflow (κάτω υπερχείλιση) έχουμε όταν προσπαθείς να διαχειριστείς στοιχεία που βρίσκονται πριν από την αρχή του οποιουδήποτε πίνακά σου, της δομής σου, κλπ.

(αυτό με το UNIX, δεν καταλαβαίνω τι εννοείς αλλά αν είναι αυτό που νομίζω ότι μπορεί να εννοείς (ονόματα αρχείων) ΔΕΝ ισχύει... μια χαρά πάνω από 8 χαρακτήρες επιτρέπει το UNIX).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 00:27

Οκ λοιπόν, ας περάσουμε τώρα στο...

Κώδικας: Επιλογή όλων
char *s = "this is a test";

Εδώ βασικά ΔΕΝ έχουμε string, έχουμε ένα string literal ή αλλιώς, μια σταθερά τιμή τύπου string, σαν να την είχαμε ορίσει με #define...

Κώδικας: Επιλογή όλων

#define STR_LITERAL "this is a test"

int main( void )
{
char *s = STR_LITERAL;
...
}

Ο πιο γρήγορος τρόπος για να καταλάβετε σε αυτό το παράδειγμα πως το s δεν είναι string αλλά απλός δείκτης, είναι να κάνετε ένα: sizeof( s ); και να διαπιστώσετε πως το μέγεθός του δεν είναι το πλήθος των χαρακτήρων του string + 1 για τον μηδενικό χαρακτήρα, αλλά είναι 4 bytes (ή 8 bytes στις 64μπιτες πλατφόρμες) που απεικονίζει το μέγεθος του δείκτη s, που είναι ίδιο για όλους τους δείκτες!

Κατόπιν, μπορείτε να δοκιμάσετε να κάνετε κάτι τέτοιο:

Κώδικας: Επιλογή όλων
s[1] = 'a;'

ή κάτι τέτοιο:
Κώδικας: Επιλογή όλων
*s = 'a;'

και να διαπιστώσετε πως ο compiler δεν θα παραπονεθεί, αλλά το πρόγραμμα θα κρασάρει!!! Ο λόγος είναι πως τα string literals ΔΕΝ μπορούμε να τα αλλάξουμε, μόνο να τα διαβάσουμε ή να τα χρησιμοποιήσουμε απείραχτα (read only).

Αν θέλουμε ντε και καλά να φτιάξουμε ένα string ορίζοντάς το ως δείκτη και όχι ως πίνακα, τότε πρέπει εκτός από τον ορισμό του δείκτη να δεσμεύσουμε και μνήμη για το μέγιστο πλήθος των χαρακτήρων που θέλουμε να φιλοξενεί + 1 για τον μηδενικό χαρακτήρα. Θα μπορούμε κατόπιν να το διαχειριστούμε σαν κανονικό string, αλλά πριν τερματίσουμε το πρόγραμμά μας θα πρέπει να απελευθερώσουμε τη μνήμη που δεσμεύσαμε...

Κώδικας: Επιλογή όλων

int main( void )
{
char *s = NULL;
s = calloc( μέγιστο_πλήθος_χαρακτήρων + 1, sizeof(char) );
...
printf("%lu\n", sizeof( s ) );
...
free( s );
return 0;

Σημειώστε πως στον παραπάνω κώδικα δεσμεύω τη μνήμη με calloc() και όχι με malloc(), διότι η calloc() γεμίζει με μηδενικά τη μνήμη που δεσμεύει, που στην περίπτωσή μας μας έρχεται... ταμάμ, διότι ισοδυναμεί με γέμισμα του string s με μηδενικούς χαρακτήρες σε όλο του το μήκος.

Ανεξάρτητα με την ευεργετική αυτή ιδιότητα σε strings που δημιουργούμε δυναμικά, να προτιμάτε πάντα την calloc() έναντι της malloc() για οποιονδήποτε τύπο δεικτών.

Και για να κλείσουμε το κομμάτι των ορισμών, στη C τα string literals μπορείτε να τα χρησιμοποιείται και απευθείας, είτε οριζοντάς τα με #define είτε όχι.

Π.χ.
Κώδικας: Επιλογή όλων

int main( void )
{
if ( "this is a test"[ 1 ] == 'h' )
...
else
...

return 0;
}

ή πιο όμορφα...
Κώδικας: Επιλογή όλων

#define MESSAGE "this is a test"
int main( void )
{
if ( MESSAGE[ 1 ] == 'h' )
...
else
...

return 0;
}

και προφανώς και με χρήση δείκτη, όπως είπαμε σήμερα...
Κώδικας: Επιλογή όλων

int main( void )
{
char *s = "this is a test";
if ( s[ 1 ] == 'h' )
...
else
...

return 0;
}

ή με συνδυασμό τους...
Κώδικας: Επιλογή όλων

#define MESSAGE "this is a test"

int main( void )
{
char *s = MESSAGE;
if ( s[ 1 ] == 'h' )
...
else
...

return 0;
}


Τα strings literals λοιπόν τα χρησιμοποιούμε σαν READ ONLY σταθερές τιμές τύπου string.

Ακούω (τυχόν) απορίες, για να συνεχίσουμε.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 05 Σεπ 2011, 00:41

Εγώ είμαι εντάξει!
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 04:26

Γεια σας παιδια!!! Λιγο μακάβρια η ώρα χεχεχε... migf κοιταξε να δεις.... εχεις απολυτο δικιο σε αυτο που λες με το οτι σιγα μην αφησουμε τον χρηστη να βάλει σαν εισοδο οτι του κατεβει στο κεφαλι :lol: :lol: (σιγα μην δεν ειχες δικιο βεβαια) χαχαχα λοιπον


1.οταν
λεω εισοδο απο τον χρηστη εννοω μεσω της fgets που έχουμε κανει παλαιοτερα. ΑΥτο εννοω. Δηλαδη το

Κώδικας: Επιλογή όλων
char s[]="";
δεν θα μπορούσε με μια fgets να περιμένει είσοδο απο τον χρήστη έτσι?

2.Οσο για αυτο που ειπα με το buffer overflow και τους 8 χαρακτήρες στο UNIX εννοουσα ονόματα χρηστών. Οχι ονοματα αρχείων ο

Κώδικας: Επιλογή όλων
char username[32];


ειναι πίνακας για τα ονοματα οποτε εφοσον επιτρεπει μεχρι 8 απο 8-32 τι γίνεται??? Και εκει ειναι που ειχα διαβασει για buffer overflow.
Κάνω λάθος πιστεύεις?

3. Στην σελίδα 115 έχεις πει (εκει που λες οτι δεν υπάρχει ξεχωριστος τυπος δεδομενων στην γλωσσα C για τα strings για αυτο και χανεται λιγο η μπαλα) πως το τρέχον μήκος ενος string δεν ισούται απαραίτητα με το συνολικό μεγεθός του... εδω σαν να μπερδεύτηκα τι εννοεις μπορεις να δειξεις ενα παραδειγμα????

migf1 έγραψε:

Αν συμφωνήσουμε όμως πως κατά βάση τα strings είναι πίνακες χαρακτήρων, τότε λέγοντας δείκτης σε string είναι σαν να λέμε δείκτης σε πίνακα χαρακτήρων. Μιλάμε δηλαδή για διπλό δείκτη και όχι για μονό ;)



Αυτο το λες επειδη εχεις ηδη εναν δεικτη που δειχνει στον πίνακα αλλα και το ονομα του πίνακα μετα ειναι απο μονος του ένας δείκτης ο οποίος δείχνει στο 1ο στοιχείο ετσι? κ.ο.κ
:geek: :geek: :geek: θελει τρελο διαβασμα ο προγραμματισμος τελικα... και οχι μονο διαβασμα απλο... να παρεις ενα βιβλιο της C και να πεις οκ ξεκιναω να διαβαζω αυτα που γραφει... θελει γενικα τρελο ψειρισμα !
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 09:03

Καλημέρα,

Star_Light έγραψε:
...
1.οταν
λεω εισοδο απο τον χρηστη εννοω μεσω της fgets που έχουμε κανει παλαιοτερα. ΑΥτο εννοω. Δηλαδη το

Κώδικας: Επιλογή όλων
char s[]="";
δεν θα μπορούσε με μια fgets να περιμένει είσοδο απο τον χρήστη έτσι?

Θα μπορούσε, με την έννοια πως ο 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' τότε ρισκάρεις σε εκείνο τον χώρο να βάλουν χάκερς δικό τους κώδικα ;) Για αυτό και όταν ορίζετε strings να τα αρχικοποιείται ΠΑΝΤΑ με μηδενικούς χαρακτήρες σε όλο το μέγιστο μήκος τους!

Αν τα δηλώνετε ως πίνακες, αυτό γίνεται έτσι:
Κώδικας: Επιλογή όλων

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.
έγραψε:
:geek: :geek: :geek: θελει τρελο διαβασμα ο προγραμματισμος τελικα... και οχι μονο διαβασμα απλο... να παρεις ενα βιβλιο της C και να πεις οκ ξεκιναω να διαβαζω αυτα που γραφει... θελει γενικα τρελο ψειρισμα !

Σε high-level γλώσσες (π.χ. python) δεν θέλει τόσο ψείρισμα, γιατί εκείνες σου δίνουν έτοιμα πάρα πολλά πράγματα.

Π.χ.στη C++ εκτός από τον κλασικό τρόπο διαχείρισης των strings για τον οποίο συζητάμε εδώ, μπορείς εναλλακτικά να χρησιμοποιήσεις την κλάση string από στην στάνταρ βιβλιοθήκη της γλώσσας, οπότε όχι μόνο παύουν να σε απασχολούν τέτοιου είδους θέματα (τα τι & πως δηλαδή που συμβαίνουν στο παρασκήνιο), αλλά έχεις έτοιμη και μια διευρυμένη γκάμα από συναρτήσεις, τελεστές και δομές για τη διαχείριση των strings. Σε low-level γλώσσες όπως η C τέτοια λειτουργικότητα είτε πρέπει να την χτίσεις μόνος σου, είτε να τη βρεις έτοιμη αλλά σε ΜΗ στάνταρ βιβλιοθήκες (για τη C σχεδόν τα πάντα υπάρχουν έτοιμα, αλλά σε ΜΗ στάνταρ βιβλιοθήκες.... όπως π.χ. η μαθηματική βιβλιοθήκη mpfr που λέγαμε προχτές ;) )
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 17:13

migf1 έγραψε:Καλημέρα,

...

Θα μπορούσε, με την έννοια πως ο compiler δεν θα παραπονιόταν, αλλά όταν έτρεχες το πρόγραμμα θα έδινε segmentation fault στο συγκεκριμένο σημείο.

Είναι δηλαδή δική σου ευθύνη να εξασφαλίσεις είτε ότι δεν θα ζητήσεις να διαβάσεις από την κύρια είσοδο το παραπάνω string, είτε πως αν το ζητήσεις τότε να έχεις εξασφαλίσει πως το έχεις ορίσει να χωράει τουλάχιστον το ελάχιστο πλήθος χαρακτήρων + τον μηδενικό για τις ανάγκες του προγράμματος σε εκείνο το σημείο.


Ok! :)
migf1 έγραψε:
Στον 9ο χαρακτήρα ( username[8] ) πρέπει να έχει το '\0' ώστε να σηματοδοτείται το τέλος του τρέχοντος μήκους του και στη συνέχεια μέχρι και τον χαρακτήρα username[31] μπορεί να έχει οτιδήποτε ... ιδανικά όλο μηδενικούς χαρακτήρες.

Το buffer σου στο συγκεκριμένο παράδειγμα είναι 32 συνεχόμενα bytes στη μνήμη (32 χαρακτήρες) οπότε όσο αναφέρεσαι σε αυτό μένοντας εντός ορίων του δεν έχεις υπερχείλιση (ούτε άνω, ούτε κάτω).

Ίσως είχες διαβάσει κάτι άλλο, ή με άλλα συμφραζόμενα, δεν ξέρω. Ίσως διάβασες πως αν δεν γεμίσεις ότι περισσεύει μέχρι τον 32ο χαρακτήρα με '\0' τότε ρισκάρεις σε εκείνο τον χώρο να βάλουν χάκερς δικό τους κώδικα ;) Για αυτό και όταν ορίζετε strings να τα αρχικοποιείται ΠΑΝΤΑ με μηδενικούς χαρακτήρες σε όλο το μέγιστο μήκος τους!

Ισως να παρανόησα εγω.... Ευχαριστω για να παω να το διορθωσω στον οδηγο που ειχα φτιαξει για το buffer overflow αν θες ριξτου και εσυ μια ματια (φυσικα ειναι πολυ εισαγωγικος δεν προσεγγιζω καν το θεμα στον πυρηνα του αλλα για να εχει μια ιδεα κάποιος) καθως αν εχω γραψει κάποια μπουρδα θα την διορθωσεις!!!! Βεβαια ακομη με προβληματιζει διοτι και αυτο που ειχα διαβασει για 8 χαρακτηρες ονοματα ισως και να μην ισχυει διοτι πχ το δικο μου hostname ειναι παραπανω πχ

Κώδικας: Επιλογή όλων
kostas@kostas-SSL:~$ hostname
kostas-SSL
kostas@kostas-SSL:~$


εκτος βεβαια και αν εννοει το kostas απο τα αριστερα και οχι το kostas μαζι με το SSL απο την αλλη που ειναι γενικα το hostname και οχι το username :)

migf1 έγραψε:
Χοντρικά, και μόνο για τα strings μιας και κάθε στοιχείο τους είναι 1 byte (1 χαρακτήρας) τρέχον μήκος είναι η τιμή που επιστρέφει η strlen( s ) και μέγιστο μήκος είναι η τιμή που επιστρέφει η sizeof( s ) (με την προϋπόθεση πως το s έχει οριστεί ως string και όχι ως string literal).

Κώδικας: Επιλογή όλων

char s[10] = "abc"; // strlen( s ) = 3, sizeof( s ) = 10




αααα οκ ναι το ειχες εξηγησει και παλαιοτερα τωρα καταλαβα! Αν ειχε οριστει σαν string literal θα ηταν char s[3]="abc"; ???

migf1 έγραψε:
Αν συμφωνήσουμε όμως πως κατά βάση τα strings είναι πίνακες χαρακτήρων, τότε λέγοντας δείκτης σε string είναι σαν να λέμε δείκτης σε πίνακα χαρακτήρων. Μιλάμε δηλαδή για διπλό δείκτη και όχι για μονό ;)

migf1 έγραψε:
Σε high-level γλώσσες (π.χ. python) δεν θέλει τόσο ψείρισμα, γιατί εκείνες σου δίνουν έτοιμα πάρα πολλά πράγματα.

Π.χ.στη C++ εκτός από τον κλασικό τρόπο διαχείρισης των strings για τον οποίο συζητάμε εδώ, μπορείς εναλλακτικά να χρησιμοποιήσεις την κλάση string από στην στάνταρ βιβλιοθήκη της γλώσσας, οπότε όχι μόνο παύουν να σε απασχολούν τέτοιου είδους θέματα (τα τι & πως δηλαδή που συμβαίνουν στο παρασκήνιο), αλλά έχεις έτοιμη και μια διευρυμένη γκάμα από συναρτήσεις, τελεστές και δομές για τη διαχείριση των strings. Σε low-level γλώσσες όπως η C τέτοια λειτουργικότητα είτε πρέπει να την χτίσεις μόνος σου, είτε να τη βρεις έτοιμη αλλά σε ΜΗ στάνταρ βιβλιοθήκες (για τη C σχεδόν τα πάντα υπάρχουν έτοιμα, αλλά σε ΜΗ στάνταρ βιβλιοθήκες.... όπως π.χ. η μαθηματική βιβλιοθήκη mpfr που λέγαμε προχτές ;) )


πολυ ενδιαφερον!!!!! Eπισης ποια η διαφορα των στάνταρ απο τις μη στάνταρ βιβλιοθήκες της γλώσσας?
Τελευταία επεξεργασία από Star_Light και 05 Σεπ 2011, 17:46, έχει επεξεργασθεί 2 φορά/ες συνολικά
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 05 Σεπ 2011, 17:16

viewtopic.php?f=9&t=17977

oριστε μια προσπαθεια οδηγου για το buffer overflow που πηγα να κανω... εσυ σαν προγραμματιστης σιγουρα θα μου πεις αν μπορω να τον αφησω ή θελει κατεβασμα καθως παραπληροφορει τον κοσμο ή δεν ειναι σωστος , να βοηθησω θελω οχι να γραφω μπουρδες και να μην βοηθαω οποιον το διαβαζει.... οποτε ειναι σημαντικο αν μπορεις κοιταξε τον λιγο δεν ειναι μεγαλος!
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 05 Σεπ 2011, 20:38

Συγνώμη βρε παιδιά, αλλά είχα σταματήσει λίγο να κοιτάζω τις δημοσιεύσεις και δεν κατάλαβα κάτι, όταν υπερχειλίζει το buffer δλδ πού πάει το υπόλοιπο κείμενο και αποτελεί πρόβλημα ασφάλειας;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 21:53

stamatiou έγραψε:Συγνώμη βρε παιδιά, αλλά είχα σταματήσει λίγο να κοιτάζω τις δημοσιεύσεις...

Μπούχτισες ε; :lol:

Σε καταλαβαίνω πάντως, γιατί όντως αρχίζουν να γίνονται βαρετά από ένα σημείο και μετά τα strings. Βασικά υπάγονται κι αυτά στη γενικότερη φιλοσοφία της C, η οποία για να μπορέσει κάποιος να γίνει παραγωγικός πρέπει πρώτα να περάσει ένα βαρετό στάδιο εκμάθησης του παρασκηνίου. Όταν το μάθει όμως, μετά θα... πετάει :)

Και ειδικά με τα strings, αν μάθετε το παρασκήνιό τους θα έχετε κάνει ένα πολύ μεγάλο κι ουσιαστικό βήμα στην εκμάθηση της γλώσσας γενικότερα!

Θέλω να μιλήσουμε λίγο και για τους έξτρα ελέγχους που χρειάζονται και μετά έχω σκοπό (αν το θέλετε κι εσείς) να χρησιμοποιήσουμε όσα έχουμε πει για να φτιάξουμε μια δική μας μικρή βιβλιοθήκη από συναρτήσεις διαχείρισης strings, οι οποίες θα είναι πιο ασφαλείς από τις αντίστοιχες στάνταρ συναρτήσεις, συχνά ταχύτερες και ελπίζω πιο εύκολες στην χρησιμοποίησή τους.

Για να πάρετε μια γεύση του τι εννοώ, φανταστείτε για παράδειγμα διαχείριση strings όπου δεν θα χρειάζεται να ασχολείστε με το αν θα γίνει buffer overflow (ή buffer underflow), δεν θα χρειάζεται να θυμάστε αν πρέπει ή δεν πρέπει να χρησιμοποιείτε & μπροστά από τα strings όταν τα περνάτε ως ορίσματα στις συναρτήσεις (θα τα περνάμε όλα χωρίς &) δεν θα χρειάζεται να ασχολείστε με το ποιο είναι το τρέχον και ποιο το μέγιστο μήκος του κάθε strings και μερικά ακόμα.

Φανταστείτε για παράδειγμα κώδικα σαν τον παρακάτω:
Κώδικας: Επιλογή όλων

#include "mystring.h"
// ----------------------------------------------------------------------------------------------------
int main( void )
{
String *s1 = string_new("this is a string);
String *s2 = string_new(" and this is another string");

string_puts( s1 ); // τυπώνει: this is a string
string_append(s1, s2); // κολλάει το s2 στο τέλος του s1, μεγαλώνοντας αυτόματα το μήκος του s1
string_puts( s1 ); // τυπώνει: this is a string and this is another string

string_text_change(s1, "abcd"); // αλλάζει το κείμενο του s1 σε "abcd", ενημερώνοντας αυτόματα το μήκος
string_puts( s1 ); // τυπώνει: abcd

string_swap( s1, s2 ); // εναλλάσσει τα κείμενα μεταξύ των s1 και s2, ενημερώνοντας τα μήκη τους

printf( "s1 = %s, s2 = %s\n", // τυπώνει: s1 = and this is another string, s2 = abcd
string_text( s1 ),
string_text( s2 )
);

string_reverse( s2 ); // αντιστρέφει το κείμενο του s2
string_puts( s2 ); // τυπώνει: dcba

string_copy(s1, string_reverse( s2 ) ); // αντιστρέφει το s2 και το αντιγράφει στο s1

printf( "s1 = %s, s2 = %s\n", // τυπώνει: s1 = abcd, s2 = abcd
string_text( s1 ),
string_text( s2 )
);

string_destroy( s1 ); // αποδεσμεύει τη μνήμη του s1
string_destroy( s2 ); // αποδεσμεύει τη μνήμη του s2

return 0;
}

είναι σαν να γράφεις σε άλλη γλώσσα, σε μια πιο εύκολη C :) Και μάλιστα, αν το κάνουμε compile με την επιλογή -std=c99 στη γραμμή εντολών του gcc (που ενεργοποιεί τα στάνταρ που θεσπίστηκαν με την αναθεώρηση C99) τότε δεν χρειάζεται καν να κάνουμε string_destroy() στο τέλος του προγράμματος, διότι η αναθεώρηση C99 υποχρεώνει τους compilers να απελευθερώνουν αυτόματα ότι μνήμη έχουμε δεσμεύσει δυναμικά (και να κλείνουν τυχόν αρχεία που έχουμε ανοίξει) πριν τερματιστεί το πρόγραμμά μας :)

Προφανώς δεν θα φτιάξουμε συναρτήσεις που θα αντικαθιστούν όλες τις στάνταρ συναρτήσεις διαχείρισης strings. Θα φτιάξουμε μερικές (αν το θέλετε) θα σας δώσω κι εγώ μερικές έτοιμες και μετά μπορούμε να δούμε πως μπορούμε να τις κάνουμε compile ως βιβλιοθήκη, την οποία μπορούμε κατόπιν να τη χρησιμοποιούμε προαιρετικά σε οποιοδήποτε άλλο πρόγραμμα φτιάξουμε :)

Πως σας φαίνεται κάτι τέτοιο; Θα έχει ενδιαφέρον;

έγραψε: και δεν κατάλαβα κάτι, όταν υπερχειλίζει το buffer δλδ πού πάει το υπόλοιπο κείμενο και αποτελεί πρόβλημα ασφάλειας;

Πάει και αντικαθιστά δεδομένα άλλων μεταβλητών του προγραμματός μας ή άλλων δεδομένων.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 05 Σεπ 2011, 21:54

Star_Light έγραψε:http://forum.ubuntu-gr.org/viewtopic.php?f=9&t=17977

oριστε μια προσπαθεια οδηγου για το buffer overflow που πηγα να κανω... εσυ σαν προγραμματιστης σιγουρα θα μου πεις αν μπορω να τον αφησω ή θελει κατεβασμα καθως παραπληροφορει τον κοσμο ή δεν ειναι σωστος , να βοηθησω θελω οχι να γραφω μπουρδες και να μην βοηθαω οποιον το διαβαζει.... οποτε ειναι σημαντικο αν μπορεις κοιταξε τον λιγο δεν ειναι μεγαλος!

Θα το κοιτάξω αύριο Κώστα, για να γράψω σήμερα για τους έξτρα ελέγχους που χρειάζεται να κάνουμε στην s_compare().
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι