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

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

Δημοσ.

Χαιρετώ! Καλή ανάσταση σε όλους!

 

Είναι αποδεκτός ο παρακάτω κώδικας ( C++ );

 

http://pastebin.com/H39HAtWG

 

Πιστεύω οτι δημιουργεί memory leak..εσείς τι λέτε; μπορώ να το αποφύγω αυτό;

Θέλω να περιορίσω στα 5 chars.. και ο τύπος να είναι char * αναγκαστικά!

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

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

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

Δημοσ.

Αντί για 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] ).

 

ΥΓ. Καλή Ανάσταση!

Δημοσ.

Αν και δεν εμφανίζει σφάλμα:

 

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 */

Δημοσ.

Ευχαριστώ πολύ!Η strcpy απο ότι είδα αντιγράφει μέχρι να βρει NULL ενώ η strncpy αντιγράφει bytes και προσθέτει στο τέλος το NULL.

Δημοσ.

Ευχαριστώ πολύ!Η 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.

Δημοσ.

Δεν μπορώ να δω τώρα όλον τον κώδικα (τι πρόβλημα έχει; )

 

Αν βασιστείς σε αυτά που σου έγραψα, θα το λύσεις (όποιο κι αν είναι). Btw η strlen() επιστρέφει το πλήθος χαρακτήρων ΠΛΗΝ του μηδενικού.

 

ΥΓ. Αν σου βγάζει προβλήματα που δεν μπορείς να λύσεις, δοκίμασε να ξαναγράψεις τον κώδικα χρησιμοποιώντας την κλάση String (αντί για τους τύπους char *).

Δημοσ.

Μου εμφανίζει αλαμπουρνέζικα στο display σαν σκουπίδια στην μνήμη..Δυστυχώς πρέπει να γίνει με char *. :(

 

Μήπως απ ότι διαβάζω εδώ πρέπει να βάλω μετά strncpy το name[10] = 0; ή surname[20] = 0; ?

Δημοσ.
>#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;}

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

Ok τώρα είναι εντάξει!Ευχαριστώ πολύ!

 

Τι ακριβώς κάνει η memset?

 

Γέμισε με μηδενικά ή με τον ειδικο 0 11/21 θέσεις μνήμης και έγραψα πάνω σε αυτήν;

Επεξ/σία από Re4cTiV3
Δημοσ.

 

Γέμισε με μηδενικά ή με τον ειδικο 0 11/21 θέσεις μνήμης και έγραψα πάνω σε αυτήν;

 

Γεμισε με μηδενικα τον πινακα. Το "ειδικο 0" ειναι 0 εφοσον το '\0' = 0

Δημοσ.

Πρέπει να κάνεις delete τη μνήμη που έχει η μεταβλητή name2. Και γενικά όπου κάνεις allocate πρέπει να κάνεις και deallocate.

Δημοσ.

Αντί για 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++.

Δημοσ.

Με την strncpy που εχω ειναι insecure; ή να το κανω με memcpy οπως λες;

 

Aντι για την memcpy μπορεις να χρησιμοποιησεις την memmove()

ειναι πιο ευελικτη επειδη μπορει να χειριστει την επικαλυψη των μπλοκ της μνήμης.

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

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

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

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

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

Σύνδεση

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

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

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