Re4cTiV3 Δημοσ. 14 Απριλίου 2012 Δημοσ. 14 Απριλίου 2012 Χαιρετώ! Καλή ανάσταση σε όλους! Είναι αποδεκτός ο παρακάτω κώδικας ( C++ ); http://pastebin.com/H39HAtWG Πιστεύω οτι δημιουργεί memory leak..εσείς τι λέτε; μπορώ να το αποφύγω αυτό; Θέλω να περιορίσω στα 5 chars.. και ο τύπος να είναι char * αναγκαστικά!
migf1 Δημοσ. 14 Απριλίου 2012 Δημοσ. 14 Απριλίου 2012 Αντί για strcpy() χρησιμοποίησε την strncpy() που σου δίνει τη δυνατότητα να ορίσεις μέγιστο πλήθος χαρακτήρων. Επίσης, το... > ... char *name2 = new char[5]; strcpy( name2, name ); name2[5] = 0; ... άλλαξέ το σε ... > ... char *name2 = new char[5]; strcpy( name2, name ); name2[4] = 0; // <----------------------------- ... διότι (και) στην C++ οι πίνακες είναι 0-indexed (που σημαίνει ότι ξεκινάνε από 0, άρα ένας πίνακας arr 5 στοιχείων πάει από arr[0] έως και arr[4] ). ΥΓ. Καλή Ανάσταση!
Stavros_Ribo Δημοσ. 14 Απριλίου 2012 Δημοσ. 14 Απριλίου 2012 Αν και δεν εμφανίζει σφάλμα: strcpy( name2, name ); εδώ πιστεύω πως ο compiler σε βοηθα να εκτελεστεί η εντολή αφού ίσο δεσμεύει παραπάνω μνήμη για να αντιγράψει τα strings. Κάτι ίσως πιο σωστό: #include <cstdlib> #include <iostream> #include <cstring> using namespace std; int main(int argc, char *argv[]) { char const * name = "Hello, World"; cout << name << " _:_ " << strlen ( name ) << endl; char *name2 = new char[5]; strncpy( name2, name, 5); cout << name2 << " _:_ " << strlen( name2 ) << endl; // system("PAUSE"); return EXIT_SUCCESS; } Δεν είμαι σίγουρος αν ζητάς αυτό... edit: /* Με πρόλαβε ο migf1 */
Re4cTiV3 Δημοσ. 14 Απριλίου 2012 Μέλος Δημοσ. 14 Απριλίου 2012 Ευχαριστώ πολύ!Η strcpy απο ότι είδα αντιγράφει μέχρι να βρει NULL ενώ η strncpy αντιγράφει bytes και προσθέτει στο τέλος το NULL.
migf1 Δημοσ. 14 Απριλίου 2012 Δημοσ. 14 Απριλίου 2012 Ευχαριστώ πολύ!Η strcpy απο ότι είδα αντιγράφει μέχρι να βρει NULL ενώ η strncpy αντιγράφει bytes και προσθέτει στο τέλος το NULL. Ναι (μέχρι να βρει '\0' αντιγράφει η strcpy(), σαν τιμή ισούται με το NULL στην C++, αλλά ως νόημα διαφέρουν... το NULL είναι για δείκτες, το '\0' είναι χαρακτήρας, ο μηδενικός χαρακτήρας). Για την strncpy(), προσθέτει ένα '\0' στο τέλος, μονάχα αν οι χαρακτήρες που αντιγράφτηκαν ήταν λιγότεροι από το 3ο της όρισμα. Αν ήταν περισσότεροι ή ίσοι, τότε δεν το προσθέτει. Γι αυτό, αν θες όντως 5 ωφέλιμους χαρακτήρες στο name2, κάνε το new με 6 (5+1, όπου 1 είναι για τον μηδενικό χαρακτήρα που πρέεπι να υπάρχει έτσι κι αλλιώς πάντα στο τέλος) και κατόπιν στην strncpy() πέρασε ως 3ο όρισμα το 5 (και όχι το 6). Αν δεν θες να ταλαιπωρείσαι με αυτά, μπορείς να χρησιμοποιήσεις την κλάση String.
Re4cTiV3 Δημοσ. 14 Απριλίου 2012 Μέλος Δημοσ. 14 Απριλίου 2012 Βασικά το θέμα που θέλω να αντιμετωπίσω είναι εδώ: http://pastebin.com/CdgH4RZM
migf1 Δημοσ. 14 Απριλίου 2012 Δημοσ. 14 Απριλίου 2012 Δεν μπορώ να δω τώρα όλον τον κώδικα (τι πρόβλημα έχει; ) Αν βασιστείς σε αυτά που σου έγραψα, θα το λύσεις (όποιο κι αν είναι). Btw η strlen() επιστρέφει το πλήθος χαρακτήρων ΠΛΗΝ του μηδενικού. ΥΓ. Αν σου βγάζει προβλήματα που δεν μπορείς να λύσεις, δοκίμασε να ξαναγράψεις τον κώδικα χρησιμοποιώντας την κλάση String (αντί για τους τύπους char *).
Re4cTiV3 Δημοσ. 14 Απριλίου 2012 Μέλος Δημοσ. 14 Απριλίου 2012 Μου εμφανίζει αλαμπουρνέζικα στο display σαν σκουπίδια στην μνήμη..Δυστυχώς πρέπει να γίνει με char *. Μήπως απ ότι διαβάζω εδώ πρέπει να βάλω μετά strncpy το name[10] = 0; ή surname[20] = 0; ?
παπι Δημοσ. 14 Απριλίου 2012 Δημοσ. 14 Απριλίου 2012 >#include <cstdlib> #include <iostream> using namespace std; class student{ private: char * name; char * surname; public: student(char * onoma, char * eponimo) { if( strlen(onoma) > 10 ) { cout << "Given name exceeds maximum length (10).\nLimiting name yo first 20 characters.\n" << endl; name = new char[ 11 ]; memset(name,0,11); strncpy( name, onoma, 10 ); } else { name = new char[ strlen(onoma) + 1 ]; strcpy( name, onoma ); } if( strlen(eponimo) > 20 ) { cout << "Given surname exceeds maximum length (20).\nLimiting name yo first 20 characters.\n" << endl; surname = new char[ 21 ]; memset(surname,0,21); strncpy( surname, eponimo, 20 ); } else { surname = new char[ strlen(eponimo) + 1 ]; strcpy( surname, eponimo ); } } void display() { cout << name << " " << surname << "\n" << endl; } }; int main(int argc, char *argv[]) { student a("re4ctiv3","InsomniaInsomniaInsomniaInsomniaInsomniaInsomnia"); a.display(); system("pause"); return 0;}
Re4cTiV3 Δημοσ. 15 Απριλίου 2012 Μέλος Δημοσ. 15 Απριλίου 2012 (επεξεργασμένο) Ok τώρα είναι εντάξει!Ευχαριστώ πολύ! Τι ακριβώς κάνει η memset? Γέμισε με μηδενικά ή με τον ειδικο 0 11/21 θέσεις μνήμης και έγραψα πάνω σε αυτήν; Επεξ/σία 15 Απριλίου 2012 από Re4cTiV3
παπι Δημοσ. 15 Απριλίου 2012 Δημοσ. 15 Απριλίου 2012 Γέμισε με μηδενικά ή με τον ειδικο 0 11/21 θέσεις μνήμης και έγραψα πάνω σε αυτήν; Γεμισε με μηδενικα τον πινακα. Το "ειδικο 0" ειναι 0 εφοσον το '\0' = 0
vamitrou Δημοσ. 16 Απριλίου 2012 Δημοσ. 16 Απριλίου 2012 Πρέπει να κάνεις delete τη μνήμη που έχει η μεταβλητή name2. Και γενικά όπου κάνεις allocate πρέπει να κάνεις και deallocate.
imitheos Δημοσ. 16 Απριλίου 2012 Δημοσ. 16 Απριλίου 2012 Αντί για strcpy() χρησιμοποίησε την strncpy() που σου δίνει τη δυνατότητα να ορίσεις μέγιστο πλήθος χαρακτήρων. Ευχαριστώ πολύ!Η strcpy απο ότι είδα αντιγράφει μέχρι να βρει NULL ενώ η strncpy αντιγράφει bytes και προσθέτει στο τέλος το NULL. Μήπως απ ότι διαβάζω εδώ πρέπει να βάλω μετά strncpy το name[10] = 0; ή surname[20] = 0; ? Όπως είπαν και τα άλλα παιδιά, η strncpy δεν θέτει 0 στον τελευταίο χαρακτήρα αν ο χώρος δεν φτάνει. Η πιο συχνή μέθοδος για να το ξεπεράσεις είναι αυτό που πρότεινε ο migf1 να δίνεις στην strncpy ένα λιγότερο χαρακτήρα από ό,τι έχεις. Έπειτα μπορείς να θέσεις 0 όπως δείχνει το link που έδωσες ή να έχεις τρέξει από την αρχή την memset που έδειξε ο Παπί (οπότε και ο τελευταίος χαρακτήρας θα είναι ήδη 0). Προ αμνημονεύτων χρόνων, πολλές εφαρμογές χρησιμοποιούσαν τα λεγόμενα "fixed-size null-filled" strings δηλαδή strings που είχαν ένα σταθερό μέγεθος και η εφαρμογή διάβαζε αυτό χωρίς να την νοιάζει αν έχει στο τέλος 0. Πολλά παιχνίδια σε DOS χρησιμοποιούσαν αυτή τη μέθοδο στα saves. Έτσι αν πχ είχαμε 8 χαρακτήρες στο όνομα του save και ονόμαζες το save σου "Re4cTiv3" αυτό θα σωζώταν ως "Re4cTiv3" χωρίς μηδενικό στο τέλος ενώ αν το ονόμαζες "Re" θα σωζώταν ως "Re\0\0\0\0\0\0". Η strncpy δημιουργήθηκε για χρήση σε αυτές τις περιπτώσεις και όχι ως "ασφαλής" εκδοχή της strcpy. Όπως διαβάζεις και στο link που έδωσες, μια καλή εναλλακτική όταν γνωρίζεις από πριν το μέγεθος είναι να χρησιμοποιείς την memcpy (ή την memmove που προτείνει το άρθρο ώστε να είσαι σίγουρος και για overlap). Μια άλλη λύση είναι να χρησιμοποιήσεις την συνάρτηση strlcpy αν την παρέχει η libc σου. Η καλύτερη λύση θα ήταν, όπως είπε και ο migf1, αν μπορούσες να χρησιμοποιήσεις μια από τις πολλές υποδομές για "strings" που παρέχει η C++.
Re4cTiV3 Δημοσ. 16 Απριλίου 2012 Μέλος Δημοσ. 16 Απριλίου 2012 Με την strncpy που εχω ειναι insecure; ή να το κανω με memcpy οπως λες;
Star_Light Δημοσ. 16 Απριλίου 2012 Δημοσ. 16 Απριλίου 2012 Με την strncpy που εχω ειναι insecure; ή να το κανω με memcpy οπως λες; Aντι για την memcpy μπορεις να χρησιμοποιησεις την memmove() ειναι πιο ευελικτη επειδη μπορει να χειριστει την επικαλυψη των μπλοκ της μνήμης.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα