freestuff.gr αρχική σελίδα
 FAQFAQ    ΑναζήτησηΑναζήτηση   Λίστα ΜελώνΛίστα Μελών   Ομάδες ΜελώνΟμάδες Μελών   <b>Εγγραφή Μέλους</b>Εγγραφή Μέλους 
 ΠροφίλΠροφίλ   Επιλογές μέλους Επιλογές   Τα bookmarks μου Τα bookmarks μου   Προσωπικά μηνύματαΠροσωπικά μηνύματα 
  διαφήμιση  

Καλώς ήρθατε στο forum μας! Για να συμμετάσχετε στις συζητήσεις θα πρέπει να είσαστε μέλος. Γίνετε μέλος τώρα!.

Πόση μνήμη καταλαμβάνει μια string μεταβλητή;


 Forum index » Δημιουργία Web Sites, Γραφικών & Προγραμματισμός » Γλώσσες Προγραμματισμού » C, C++
Moderators:  Super-Moderators, WebDev Moderators
Εισαγωγή νέου Θέματος   Απάντηση στο Θέμα Σελίδα 1 από 1 [4 Μηνύματα]      Bookmarks Tags: string Mark the topic unread :: Προηγούμενο θέμα :: Επόμενο θέμα
ΑποστολέαςΜήνυμα
lakritidis


Μέλος από: 04 Αυγ 2005
Μηνύματα: 256+
Περιοχή: Katerini
View users profile Send email to user Visit posters website
ΜήνυμαΣτις: 24 Φεβ 2008 13:13    Θέμα: Πόση μνήμη καταλαμβάνει μια string μεταβλητή; Απάντηση με παράθεση  Mark this post and the followings unread

Η ερώτηση μοιάζει απλή.

κώδικας:
string test1 = "0123456789";
string test2 = "0123456789012345678901234567890123456789";

cout << sizeof test1 << endl;
cout << sizeof test2 << endl;

// Τυπώνει
// 28
// 28


Η sizeof τυπώνει 28 και για τις δύο περιπτώσεις, ανεξαρτήτως του τι περιέχει μέσα το string. Ψάχνοντας στο Internet βρήκα ότι h sizeof επιστρέφει το μέγεθος του αντικειμένου std::string.

Αυτό το 28 δεν είναι standard και εξαρτάται από την υλοποίηση και τα optimizations που υπάρχουν για τα strings σε κάθε compiler. Πχ κάποιος αναφέρει ότι ο ίδιος κώδικας σε g++ σε ubuntu τυπώνει 4.

Αντίθετα, το ακόλουθο τυπώνει αυτό που περιμέναμε:

κώδικας:
cout << test1.size() << endl;
cout << test2.size() << endl;

// Τυπώνει
// 10
// 40


Ερωτήσεις
1. Ή τα strings δεν έχουν termination character όπως οι char, ή έχουν και η size τον αγνοεί. Τι από τα δύο συμβαίνει;
2. Τελικά πόση μνήμη καταλαμβάνει πχ ή test1? 28bytes; 10bytes; ή μήπως 11bytes (συν termination character);
MannyCalavera


Μέλος από: 11 Δεκ 2007
Μηνύματα: 13

View users profile Visit posters website
ΜήνυμαΣτις: 26 Φεβ 2008 17:13    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

1) Δε συμβαίνει τίποτα από τα δύο. Έχουν termination character, απλώς το είπες και μόνος σου: "η sizeof επιστρέφει το μέγεθος του αντικειμένου std::string" και όχι τον αριθμό των χαρακτήρων που έχει αποθηκεύσει.

Πρέπει να ξεκαθαρίσεις το εξής: Άλλο το αντικείμενο std::string και άλλο το string "0123456789". Το std::string είναι ένα αντικείμενο που ο ρόλος του στην ουσία είναι να διαχειρίζεται το string που του δίνεις και να σε διευκολύνει στις συνήθεις λειτουργίες που κάνει κάποιος σε ένα string (αντιγραφή, πρόσθαφαίρεση χαρακτήρων, συνένωση strings, κ.α.), κάτι που σε διαφορετική περίπτωση έπρεπε να κάνεις με functions της C (strcpy, strlen, strcat, κλπ.).

Το std::string, ως καλός διαχειριστής, δε σ'αφήνει να επέμβεις απ'ευθείας στο string (δηλ. εκεί που πραγματικά αποθηκεύονται οι χαρακτήρες "0123456789" στη μνήμη) για λόγους ασφάλειας. Όλες οι λειτουργίες πάνω στο string γίνονται μέσω των member functions και operators του std::string.
Θες να δεις πόσους χαρακτήρες έχει? Γράφεις test1.length()
Θες να μάθεις πόση μνήμη πιάνει? Γράφεις test1.size()

Και έρχομαι στο δεύτερο ερώτημά σου.

2) Τι γίνεται λοιπόν όταν δίνεις sizeof(test1) ?
Στην ουσία ζητάς να μάθεις το χώρο που καταλαμβάνει στη μνήμη το αντικείμενο std::string.
Η τιμή που θα σου δώσει, δηλαδή, είναι ο χώρος που καταλαμβάνει ο διαχειριστής, και όχι το πραγματικό string.

Τώρα γιατί βγάζει αυτό το 28, είναι άλλο θέμα, όχι και τόσο εύκολο να απαντηθεί:
Το μέγεθος ενός αντικειμένου (class, struct) καθορίζεται από πολλούς παράγοντες που χοντρικά είναι οι εξής

1. Από το σύνολικό μέγεθος των data members που περιέχει (εξαιρούνται οι static μεταβλητές γιατί δε θεωρούνται μέλη του αντικειμένου)

2. Από τη σειρά με την οποία δηλώνονται αυτά τα data members, όσο περίεργο κι αν ακούγεται αυτό. Έχει να κάνει με την έννοια του data structure alignment

3. Από το inheritance. Αν το αντικείμενό σου "κληρονομεί" από άλλο αντικείμενο, τότε στο μέγεθός του πρέπει να προστεθεί και το μέγεθος του "πατρικού" αντικειμένου (base class)

4. Από το virtual inheritance. Για κάθε virtual inheritance προσθέτουμε +4byte (νομίζω).

5. Από τον compiler. Διαφορετικοί compilers βγάζουν διαφορετικά sizeof για το ίδιο αντικείμενο(ειδικά αν έχει inheritance). Βέβαια τα 4byte που έγραψες για τον g++ δεν ακούγονται ρεαλιστικά(μήπως αυτός που το έγραψε μέτρησε το μέγεθος του δείκτη σε αντικείμενο std::string??). Οι διαφορές τους έχουν συνήθως να κάνουν με το padding (δες data structure alignment) και το virtual table (βλ. 6).

6. Από το αν έχει virtual methods. Τα πράγματα δεν είναι τόσο απλά εδώ. Εξαρτάται από τον compiler και πως υλοποιεί το vtable.


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

_________________
The living still give me the creeps
lakritidis


Μέλος από: 04 Αυγ 2005
Μηνύματα: 256+
Περιοχή: Katerini
View users profile Send email to user Visit posters website
ΜήνυμαΣτις: 26 Φεβ 2008 18:20    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Ευχαριστώ για την αναλυτική σου απάντηση.

Απλά στην εφαρμογή που φτιάχνω με ενδιαφέρει να γνωρίζω που πηγαίνει και το τελευταίο byte. Βλέπω ότι αυτό είναι ψιλοδύσκολο με χρήση strings, επομένως επιστρέφω σα βρεγμένη γάτα στα απλά c-strings (char), όπου σίγουρα το μέγεθος στη μνήμη είναι 1byte για κάθε χαρακτήρα (ή μήπως όχι;).

Μιας και είσαι γνώστης του αντικειμένου, έχω υλοποιήσει ένα binary tree με τη βοήθεια της παρακάτω class.

κώδικας:
class Lexicon {
   public:
      // Public Functions for Lexicon Manipulation
      Lexicon();
      ~Lexicon();
      // Count Lexicon Members
      int countNodes();
      // Insert/update a term to/in Lexicon
      class Lexicon* InsertNode(wchar_t*& term, int* termid, int address);
      // Calculate memory occupied by Lexicon
      void OccupiedMemory(int* Memory);
      // Print the Lexicon (Screen)
      void display();
      // Write the Lexicon to disk (LexiconFile)
      void flush(wofstream& LexiconFile);
   private:
      // Private Lexicon Members
      wchar_t* term;      // Term
      int termId;         // Term Id
      int docfreq;      // Term frequency
      int il_address;      // Inverted List Address on disk
      // Branch Pointers
      class Lexicon* leftChild;
      class Lexicon* rightChild;
} *p;


Με βάση τα όσα είπες υποθέτω ότι κάθε κόμβος του δέντρου καταλαμβάνει στη μνήμη

4 bytes για τον pointer σε wchat_t +
4 bytes για τον integer termid +
4 bytes για τον integer docfreq +
4 bytes για τον integer il_address +
4 bytes για τον pointer στο δεξί child του κόμβου +
4 bytes για τον pointer στο αριστερό child του κόμβου
= 24 bytes

Και συνολικά το δεντρο πιάνει 24 * (πλήθος κόμβων) bytes στη μνήμη.

Σωστά;

Edit: Εκπληκτικό αυτό με το data structure alignment. Αυτή η δομή
κώδικας:
struct MixedData
{
    char Data1;
    short Data2;
    int Data3;
    char Data4;
};


θα περιμέναμε να καταλαμβάνει 8 bytes και όμως καταλαμβάνει 12! Με μια απλή αναδιάταξη των members της, ρίχνουμε το μέγεθος στα 8 bytes

κώδικας:
struct MixedData
{
    short Data2;
   char Data1;
   char Data4;
    int Data3;
};

MannyCalavera


Μέλος από: 11 Δεκ 2007
Μηνύματα: 13

View users profile Visit posters website
ΜήνυμαΣτις: 27 Φεβ 2008 15:55    Θέμα: Απάντηση με παράθεση  Mark this post and the followings unread

Λογικά κάθε Lexicon έχει μέγεθος 24 και σε vc++ compiler και σε gcc και όλα το tree θα έχει μέγεθος 24*κόμβους .

Βέβαια αν δεν το δοκιμάσεις ποτέ μην είσαι βέβαιος, όπως είπα και πριν. Σε MingW (gcc 3.4.5) που το δοκίμασα έχει όντως μέγεθος 24.

Το data alignment είναι ένας από τους λόγους που ένας καλός προγραμματιστής πρέπει να έχει και καλή γνώση του hardware. Στην πλειοψηφία των εφαρμογών δεν πρόκειται ποτέ να απασχολήσει, αλλά υπάρχουν ειδικές περιπτώσεις όπου γίνεται σημαντικό (όταν προγραμματίζεις μια συσκευή με πολύ περιορισμένη μνήμη, π.χ. ένα κινητό).
Πρόσεχε μόνο, διότι ένα misaligned structure μπορεί να καταλαμβάνει λιγότερο χώρο, ότι κερδίζεις όμως σε μνήμη το χάνεις σε ταχύτητα.

_________________
The living still give me the creeps
Εμφάνιση Μηνυμάτων:   
Εισαγωγή νέου Θέματος   Απάντηση στο Θέμα Σελίδα 1 από 1 [4 Μηνύματα] Mark the topic unread :: Προηγούμενο θέμα :: Επόμενο θέμα
 Forum index » Δημιουργία Web Sites, Γραφικών & Προγραμματισμός » Γλώσσες Προγραμματισμού » C, C++
Τώρα είναι 29 Μαρ 2017 07:24 | All times are UTC + 2


Email This Page to Someone! add to Favorites

     Powered by p h p B B © 2001,2005 p h p B B Group
Για άμεση επικοινωνία με τον διαχειριστή του freestuff.gr στο email: freestuff.gr(παπάκι)gmail.com


Copyright © 1999-2013 Freestuff.gr All Rights Reserved  
Version Aegean, designed by N. Tsaganos