Προς το περιεχόμενο

C: Περίεργη συμπεριφορά της free()?


geomagas

Προτεινόμενες αναρτήσεις

 

No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case,destination shall not be considered a null terminated C string (reading it as such would overflow).

 

Μια και ο παπί με τον defacer έδωσαν τη λύση (την καλύτερη που μπορεί να δοθεί υπό τις δεδομένες συνθήκες) και μέχρι να γυρίσει ο geomagas από το φαγητό φέρνοντας νέο input στο πρόβλημα, παίρνω το θάρρος να ψιλο βγω offtopic και να πω αυτό που έχω πει πολλές φορές.

 

Λόγω ότι πολλές συναρτήσεις αντιγραφής δεν επέτρεπαν έλεγχο στο μήκος που αντιγράφεται, εισήχθησαν μερικές νέες συναρτήσεις με ίδιο όνομα αλλά με "n" στο όνομά τους για να μπορείς να ορίσεις το μέγεθος της αντιγραφής. Έτσι όπως έχουμε την strcat έχουμε την strncat, όπως έχουμε την sprintf έχουμε την snprintf, κτλ.

 

Έτσι θεωρήθηκε και επικράτησε ως άποψη ότι η "n" συναρτήσεις είναι οι "safe" εκδόσεις των απλών και συστήνονται σε πολλά βιβλία και οδηγούς.

 

Στην περίπτωση όμως της strncpy το όνομα ήταν λίγο άστοχο γιατί η strncpy _δεν_ εισήχθη για τον ίδιο λόγο με τις υπόλοιπες το οποίο βλέπουμε και στην περιγραφή της λειτουργίας της ένα κομμάτι της οποίας ανέφερε ο defacer.

 

Η strncpy δεν φτιάχθηκε για να δουλεύει με "C strings" δηλαδή σειρές χαρακτήρων που τελειώνουν με τον χαρακτήρα μηδέν αλλά με σειρές χαρακτήρων σταθερού μεγέθους για αυτό το λόγο όταν το source είναι μεγαλύτερο δεν εισάγει το NUL στο τέλος και όταν το source είναι μικρότερο κάνει pad με μηδενικά.

 

Αυτού του είδους τα "strings" σταθερού μεγέθους χρησιμοποιούνταν πολύ συχνά ως πεδία σε διάφορες δομές όπως παλιά στο unix και επίσης ήταν η συνήθης μέθοδος αποθήκευσης στα savegames των παιχνιδιών σε DOS (και συνεχίζονται ακόμη και τώρα σε διάφορα παιχνίδια).

 

Με λίγα λόγια, όταν μεταχειριζόμαστε "c strings" η strncpy δεν είναι ποτέ η λύση. Όταν μας έρχεται στο μυαλό να χρησιμοποιήσουμε strncpy ας το ξανασκεφτόμαστε.

  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 59
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Παίζεις με τη φλόγα... :P

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

 

εγώ σχεδόν την έχω καταργήσει την malloc() (εκτός από πολύ ειδικές περιπτώσεις) και την έχω αντικαταστήσει με την calloc().

 

Αλλά έχει trade-off. Αν βασίζεσαι στο "immediate crash is good" μάλλον δεν θα σε βολέψει. Αν και στην προκειμένη περίπτωση που συζητάμε (και στις περισσότερες) με την malloc() δεν έχεις εγγυημένα immediate crash.

  

Ένα άλλο καλό που έχει η calloc είναι ότι (ενδέχεται να) σου παρέχει προστασία από overflows. Δεν το ορίζει το πρότυπο δυστυχώς αλλά πολλές υλοποιήσεις το κάνουν.

 

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
	int *m, *c;
	size_t s;

	s = (size_t) -1;
	s /= 4096;
	s++;

	m = malloc(s * s);
	printf("m = %p err = %d\n", (void *)m, errno);
	c = calloc(s, s);
	printf("c = %p err = %d\n", (void *)c, errno);

	free(c);
	free(m);

	return 0;
}
Έξοδος:
m = 0x636010 err = 0
c = (nil) err = 12
Το s * s δεν χωράει φυσικά οπότε γίνεται υπερχείλιση και η malloc δεσμεύει ένα πολύ μικρότερο ποσό μνήμης. Η calloc επειδή δέχεται ξεχωριστά τα ορίσματα έχει τη δυνατότητα να ελέγξει αν θα υπάρξει υπερχείλιση και έτσι σου επιστρέφει NULL και error 12 το οποίο σε linux είναι ENOMEM δηλαδή αυτό που έπρεπε να κάνει.
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@defacer, τώρα είδα το edit. Τελικά αυτό ήταν, και με έναν έξτρα έλεγχο, σε πρώτη φάση όλα δουλεύουν μια χαρά:

    char *str;
    size_t len=*srcpos-token_start;
    if(len&&(str=malloc(len+1)))
        strncpy(str,token_start,*srcpos-token_start);
    else
        str="";

Thanx!

 

@imitheos: Πολύ διαφωτιστικά αυτά περί strncpy. Αυτός είναι ακριβώς ο λόγος που τη θεώρησα κι εγώ δεδομένη, και δεν το έψαξα παραπάνω (τη calloc() θα πρέπει να τη "μελετήσω").

 

Τώρα, αν θέλουμε να το φιλοσοφήσουμε, ποιος θα ήταν ο πιο "κομψός" τρόπος να παρουμε ένα null-terminated αντίγραφο του string που "ορίζεται" από τους char *start και char *end>=start, μη συμπεριλαμβανομένου του *end;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τώρα, αν θέλουμε να το φιλοσοφήσουμε, ποιος θα ήταν ο πιο "κομψός" τρόπος να παρουμε ένα null-terminated αντίγραφο του string που "ορίζεται" από τους char *start και char *end>=start, μη συμπεριλαμβανομένου του *end;

Το "κομψό" είναι σχετικό, ανάλογα τις ανάγκες και ανάλογα το πόσο ελεγχόμενα έχεις τα start και end. Π.χ. αν είσαι σίγουρος πως είναι πάντα non-NULL με end >= star και πως τα 2 είναι δείκτες στο ίδιο object, τότε αυτό που σου έδειξα με calloc() και strncpy() δεν πρόκειται να σε κρεμάσει ποτέ :P. Στην χειρότερη (δηλαδή όταν start == end ) θα πάρεις η NULL σε αποτυχία, ή ένα cstring 1ος μηδενισμένου byte (η calloc() σου εγγυάται πως αν πετύχει τότε η μνήμη που σου επιστρέφει έχει μηδενισμένα όλα της τα bytes).

 

Αντί για strncpy() μπορείς να χρησιμοποιήσεις memcpy() ή οποία ανάλογα με τo implementation μπορεί να είναι και ταχύτερη. Για να αποφύγεις και την περίπτωση όπου end < start (περίπτωση κατά την οποία η size_t αφαίρεση τους θα σου δώσει έναν πολύ μεγάλο unsigned) μπορείς να προσθέσεις έναν έξτρα έλεγχο. Κάπως έτσι..

char *str = NULL;
if ( end >= start )
{
    size_t len = end - start;
    str = calloc( 1, 1+len );
    if ( str ) {
        memcpy(str, start, len /* * sizeof(char) */ );
    }
}
return str;
ή μπορείς να κάνεις swap τα start & end (not a very good idea).

 

Μπορείς να φτιάξεις και αυτόνομη συνάρτηση, και να κάνεις όσους πολλούς ή όσους λίγους ελέγχους θέλεις μέσα της. Εγώ π.χ. στην libs που είχα ξεκινήσει κάποτε (αλλά την έχω παρατημένη) είχα φτιάξει δικιά μου εκδοχή της strncpy() η οποία εγγυόταν μηδενισμένο τέλος, εις βάρος ενός χαρακτήρα από το len που της περνάς: s_strncpy(). Εδώ είναι ο κώδικάς της αλλά επειδή είναι μέρος library κάνει 32000 ελέγχους πριν ξεκινήσει το ουσιαστικό της κομμάτι :lol:

 

ΥΓ. Ωραία Εθνική έχουμε :(

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τώρα, αν θέλουμε να το φιλοσοφήσουμε, ποιος θα ήταν ο πιο "κομψός" τρόπος να παρουμε ένα null-terminated αντίγραφο του string που "ορίζεται" από τους char *start και char *end>=start, μη συμπεριλαμβανομένου του *end;

 

Αν έχεις strndup τότε αυτή η ίδια αν και θα είναι πιο αργή από τη manual λύση με memcpy επειδή στην προκειμένη έχεις περισσότερη πληροφορία στα χέρια σου (το ακριβές μήκος του string) από αυτή που χρειάζεται η strndup (το μέγιστο αποδεκτό μήκος του string) και δεν τη χρησιμοποιείς.

 

Αν δεν έχεις τότε κάτι σαν αυτό που έδωσε παραπάνω ο migf1, απλώς εγώ θα έβαζα malloc αντί για calloc, αφού ήδη ξέρεις ότι θα γράψεις σε ολόκληρο το buffer δεν έχει νόημα να το μηδενίσεις πρώτα.

 

H calloc δεν έχει τίποτα να μελετήσεις. :-)

 

Επίσης στο διορθωμένο κώδικά σου όπως είπε κι ο ημίθεος η strncpy δεν έχει νόημα. Γιατί όχι σκέτη memcpy και με το χέρι το null terminator? Αν το είχες κάνει έτσι εξαρχής δε θα είχες και bug in the first place.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

...

Αν δεν έχεις τότε κάτι σαν αυτό που έδωσε παραπάνω ο migf1, απλώς εγώ θα έβαζα malloc αντί για calloc, αφού ήδη ξέρεις ότι θα γράψεις σε ολόκληρο το buffer δεν έχει νόημα να το μηδενίσεις πρώτα.

...

Έχει νόημα, αποφεύγεις το bug που εντόπισες στον κώδικα του geomagas.
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@defacer, τώρα είδα το edit. Τελικά αυτό ήταν, και με έναν έξτρα έλεγχο, σε πρώτη φάση όλα δουλεύουν μια χαρά:

    char *str;
    size_t len=*srcpos-token_start;
    if(len&&(str=malloc(len+1)))
        strncpy(str,token_start,*srcpos-token_start);
    else
        str="";
Thanx!

 

@imitheos: Πολύ διαφωτιστικά αυτά περί strncpy. Αυτός είναι ακριβώς ο λόγος που τη θεώρησα κι εγώ δεδομένη, και δεν το έψαξα παραπάνω (τη calloc() θα πρέπει να τη "μελετήσω").

 

Τώρα, αν θέλουμε να το φιλοσοφήσουμε, ποιος θα ήταν ο πιο "κομψός" τρόπος να παρουμε ένα null-terminated αντίγραφο του string που "ορίζεται" από τους char *start και char *end>=start, μη συμπεριλαμβανομένου του *end;

 

Υπάρχουν δεκάδες τρόποι για την αντιγραφή με πιο κομψός να είναι διαφορετικός για κάθε προγραμματιστή :)

 

Με ταξινόμηση από τη χειρότερη προς την καλύτερη (τελείως υποκειμενικά με ποια σειρά θα τις χρησιμοποιούσα εγώ) έχουμε:

 

Μία μέθοδος που χρησιμοποιούν όσοι είναι υπέρμαχοι της strncpy είναι η παρακάτω:

 

strncpy(dest, src, len);
dest[len - 1] = '\0';
Αν το src είναι μικρότερο του dest, τότε η strncpy θα εισάγει padding μέχρι να πιάσει τον αριθμό len. Αν το src είναι μεγαλύτερο, τότε δεν θα εισάγει το 0 αλλά το εισάγεις εσύ χειροκίνητα. Έτσι δεν θα έχεις πρόβλημα αλλά δεν κερδίζεις τίποτα γιατί το ίδιο ακριβώς θα επιτύγχανες και με κάποια άλλη συνάρτηση.

 

Άλλος τρόπος είναι να χρησιμοποιήσεις την strncat.

dest[0] = '\0';
strncat(dest, src, len);
Η strncat όπως λέει και το όνομά της έχει φτιαχτεί για να ενώνει δύο strings. Αυτό που κάνει είναι να διανύει το dest μέχρι να βρει το τελικό 0. Έπειτα αρχίζει να γράφει το src σβήνοντας το μηδέν και αφού γράψει το src εισάγει ένα τελικό 0. Για να χρησιμοποιηθεί για απλή αντιγραφή αρκεί να γράψουμε το 0 σαν πρώτο χαρακτήρα του dest. Σκέψου δηλαδή ότι ενώνουμε το src με το "κενό string".

 

Η strncat έχει το καλό ότι εισάγει πάντα ένα τελικό κενό οπότε δεν έχουμε το πρόβλημα της strncpy. Επίσης, σε περίπτωση που δεν γίνεται κατανοητό από τη προηγούμενη πρότασή μου, αξίζει να αναφέρουμε ότι η strncat γράφει ένα παραπάνω χαρακτήρα από το νούμερο που της δίνουμε. Έγραψα len στο παράδειγμά μου επειδή έχεις μεριμνήσει για το +1 στη κλήση της malloc. Αν το len σήμαινε το μέγεθος του dest, τότε θα έπρεπε να δώσω len - 1 στην strncat.

 

Ένα άλλο θετικό που έχει αυτή η μέθοδος είναι ότι είναι πιο γρήγορη από την strncpy επειδή δεν εισάγει το padding.

 

Αυτή που χρησιμοποιώ πιο συχνά είναι η memcpy.

memcpy(dest, src, len);
dest[len] = '\0';
Η memcpy δεν είναι συνάρτηση για c strings αλλά αντιγράφει ό,τι της δώσεις. Για αυτό το λόγο θα είναι σε κάποιες περιπτώσεις πιο αργή από την strncat αλλά σίγουρα πιο γρήγορη από την strncpy. Η ίδια παρατήρηση για το len - 1 που έκανα πριν ισχύει και εδώ.

 

Αν ο compiler σου υποστηρίζει την έκδοση C11 υπάρχει και η strcpy_s συνάρτηση αλλά πιστεύω είναι overkill για το 99.9% των περιπτώσεων.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Έχει νόημα, αποφεύγεις το bug που εντόπισες στον κώδικα του geomagas.

 

Κάνεις alloc και zero len + 1 bytes, και μετά κάνεις overwrite τα πρώτα len από αυτά με memcpy.

 

Αντί γι' αυτό, σκέτο alloc len + 1 bytes, overwrite τα πρώτα len από αυτά με memcpy και στο τελευταίο γράφεις 0 με το χέρι.

 

Είναι το ίδιο ακριβώς πράγμα μόνο που τα πρώτα len bytes τα γράφεις μόνο μια φορά αντί για 2 => faster. Το bug δε μπορεί να εμφανιστεί επειδή πάντα len >= 0 άρα το τελευταίο byte (len + 1) όπου γράφεις 0 πάντα θα υπάρχει.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

ΥΓ. Ωραία Εθνική έχουμε :(

...Να υποθέσω ότι χάσαμε; (άμπαλος εδώ... με την καλή έννοια! :P )

 

Το "κομψό" είναι σχετικό,

Ναι εννοείται, απλά θέλω να πάρω απόψεις.

 

ανάλογα τις ανάγκες και ανάλογα το πόσο ελεγχόμενα έχεις τα start και end. Π.χ. αν είσαι σίγουρος πως είναι πάντα non-NULL με end >= star και πως τα 2 είναι δείκτες στο ίδιο object,

Ναι για αυτή την περίπτωση μιλάω. Και τα δύο δείχνουν μέσα στο ίδιο null-terminated string (μπορεί να δείχνουν και το termination), και end>=start. Μάλιστα, αν *end=='\0', τότε και start==end, αλλά δεν ισχύει και αντίστροφα.

 

H calloc δεν έχει τίποτα να μελετήσεις. :-)

Το ίδιο πίστευα και για την strncpy... και ιδού τα ολέθρια αποτελέσματα! :)

 

Επίσης στο διορθωμένο κώδικά σου όπως είπε κι ο ημίθεος η strncpy δεν έχει νόημα. Γιατί όχι σκέτη memcpy και με το χέρι το null terminator? Αν το είχες κάνει έτσι εξαρχής δε θα είχες και bug in the first place.

Δεν είπα "όχι" σε τίποτα...

 

@imitheos: Να υποθέσω ότι, από τις τρεις, η λύση με malloc είναι η πιο αποδοτική, έτσι;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

@imitheos: Να υποθέσω ότι, από τις τρεις, η λύση με malloc είναι η πιο αποδοτική, έτσι;

Τι εννοείς λύση με malloc ? Σε όλες τις περιπτώσεις θα χρειαστείς να καλέσεις την malloc. Αν εξαιρέσεις την strndup που ανέφερε ο defacer, καμμία από αυτές τις συναρτήσεις αντιγραφής δεν δεσμεύει μνήμη.

 

Edit: Τώρα που το ξανακοιτάω, λες "από τις τρεις" οπότε υποθέτω αναφέρεσαι στις τρεις μεθόδους που ανέφερα. Άρα μάλλον αντί για malloc εννοείς αν η memcpy είναι πιο αποδοτική, έτσι ?

 

Αν ναι κανείς δεν το ξέρει αυτό :P

 

#include <string.h>
#include <stdio.h>

int main(void)
{
	char src[10] = "Test";
	char dest[10] = { 50, 50, 50, 50, 50, 50, 50, 50, 50, 50 };
	int i;

	dest[0] = '\0';
	strncat(dest, src, 9);
	printf("Meta apo strncat\n");
	for (i = 0 ; i < 10; i++) {
		printf ("%02d(%c) ", dest[i], dest[i]);
	}
	printf("\n");
	memcpy(dest, src, 10);
	printf("Meta apo memcpy\n");
	for (i = 0 ; i < 10; i++) {
		printf ("%02d(%c) ", dest[i], dest[i]);
	}
	printf("\n");

	return 0;
}
Έξοδος:
Meta apo strncat
84(T) 101(e) 115(s) 116(t) 00() 50(2) 50(2) 50(2) 50(2) 50(2) 
Meta apo memcpy
84(T) 101(e) 115(s) 116(t) 00() 00() 00() 00() 00() 00() 
Δες το παραπάνω χαζό κώδικα. Θέλεις να αντιγράψεις το src στο dest οπότε λες θα βάλω ως len το 10 που έχουν και τα δύο buffers. Αυτό το 10 όμως στη περίπτωση της strncat είναι το μέγιστο που θέλεις να γράψει και αν βρει πιο μπροστά μηδέν θα σταματήσει εκεί. Για αυτό το λόγο βλέπεις το dest να έχει Test μετά το 0 και μετά απείραχτα τα 50άρια. Η memcpy δεν ασχολείται με c strings και μηδενικά αλλά αντιγράφει όσο της πεις.

 

Βλέποντας κάποιος αυτό θα πει ότι η strncat γράφει 5 bytes ενώ η memcpy γράφει 10 bytes άρα είναι πιο αργή. Θεωρητικά είναι όντως έτσι. Πρακτικά όμως (και ξεχνώντας ότι η διαφορά θα είναι μηδαμινή μπροστά στο συνολικό χρόνο εκτέλεσης του προγράμματος) δεν ισχύει αυτό.

 

Στις περισσότερες περιπτώσεις η memcpy καταλήγει να είναι πιο γρήγορη γιατί έχει πολύ καλύτερη υλοποίηση.

 

Για παράδειγμα στο FreeBSD οι συναρτήσεις strlcat, strncat, strncpy όλες δουλεύουν με έναν-έναν τους χαρακτήρες όπως βλέπεις. Αντίθετα η memcpy (ή bcopy) ευθυγραμμίζει πρώτα σε ένα word (στις περισσότερες περιπτώσεις μη απαραίτητο γιατί η malloc επιστρέφει aligned δείκτες) και έπειτα αντιγράφει ένα word κάθε φορά αντί για ένα χαρακτήρα.

 

Ας έρθουμε τώρα στην υλοποίηση της glibc του linux που όπως πάντα είναι πιο πολύπλοκη. Οι συναρτήσεις strncat, strncpy χρησιμοποιούν όπως βλέπεις "loop unrolling" για ταχύτητα και χωρίζουν το len σε 4 και εξετάζουν 4 χαρακτήρες κάθε φορά έναν-έναν όμως γιατί πρέπει να επιστρέψουν αν βρουν μηδέν. Αντίθετα η memcpy και εδώ αντιγράφει ένα word τη φορά (και ένα page αν το επιτρέπει η αρχιτεκτονική).

 

Εκτός από αυτή τη generic συνάρτηση σε c υπάρχουν και εξειδικευμένες συναρτήσεις σε assembly στον κατάλογο sysdeps που μπορούν να εκμεταλλευτούν MMX, SSE, κτλ ό,τι παρέχει ο επεξεργαστής για να έχουν ακόμη μεγαλύτερη ταχύτητα (και η strncpy και οι άλλες υλοποιούνται σε assembly αλλά συνήθως η memcpy είναι πιο γρήγορη λόγω ότι δεν χρειάζεται να ελέγχει μηδενικά και να επιστρέφει το char pointer).

 

Με λίγα λόγια ανάλογα την αρχιτεκτονική και την υλοποίηση της libc θα έχεις και διαφορετικό αποτέλεσμα. Το θέμα όμως είναι ότι αν το πρόγραμμά σου δεν αντιγράφει τόνους δεδομένων από buffer σε buffer, η διαφορά στη ταχύτητα δεν θα πρέπει να σε καίει. Χρησιμοποιείς την συνάρτηση που σε βολεύει και δεν σου προκαλεί προβλήματα.

Επεξ/σία από imitheos
  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τι εννοείς λύση με malloc ? Σε όλες τις περιπτώσεις θα χρειαστείς να καλέσεις την malloc. Αν εξαιρέσεις την strndup που ανέφερε ο defacer, καμμία από αυτές τις συναρτήσεις αντιγραφής δεν δεσμεύει μνήμη.

 

Ώπα sorry, εννοούσα τη λύση με memcpy! :D

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το μόνο που έχω να προσθέσω στα παραπάνω του ημίθεου, χωρίς αυτό να αλλάζει το συμπέρασμά του ότι το καλύτερο είναι να χρησιμοποιείς αυτό που "ταιριάζει καλύτερα" επειδή οι διαφορές στην απόδοση είναι καθαρά ακαδημαϊκές:

 

Στην προκειμένη όλα τα checks για το αν ο τάδε χαρακτήρας είναι 0 θα πάνε άκλαφτα -- το ξέρουμε αυτό επειδή επεξεργαζόμαστε δεδομένα από είσοδο όπου ο χαρακτήρας 0 δεν είναι valid είσοδος και αν υπάρχει θα έχει κάνει τη δουλειά του πριν φτάσουμε στο σημείο να κάνουμε memcpy κλπ κλπ.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Στην προκειμένη όλα τα checks για το αν ο τάδε χαρακτήρας είναι 0 θα πάνε άκλαφτα -- το ξέρουμε αυτό επειδή επεξεργαζόμαστε δεδομένα από είσοδο όπου ο χαρακτήρας 0 δεν είναι valid είσοδος και αν υπάρχει θα έχει κάνει τη δουλειά του πριν φτάσουμε στο σημείο να κάνουμε memcpy κλπ κλπ.

 

Με μπέρδεψες τώρα. Σε ποια checks αναφέρεσαι; Και γιατί το \0 δεν είναι valid είσοδος;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...