Speichereintelung



  • Hallo zusammen,

    ich habe da mal eine Frage zur Speicherverwaltung des PC's.

    Angenommen ich habe folgende Klasse:

    class point
    {
      public:
        uint32 x;
        uint32 y;
        uint8 a;
        uint16 b;
        float64 c;
    }
    

    Klasseninfo Länge : 4bytes + 4bytes + 1 byte + 2 byte + 8bytes = 19bytes

    Mein Ziel is es diese Klasse über den seriellen Port zu senden.
    Meine Methode zum senden ist writeData(char* ap_buffer , int ai_bufferSize)

    Wo ich nicht so sicher ist, ist bei der Bufferlänge. Irgendwie ist mir noch vom Unterricht etwas in den Sinn gekommen das der Computer für die Speicherreservierung immer Addressen braucht die durch 16, 32 , 64 teilbar sind. Heisst das nun er reserviert für ein char 16, 32, 64 byte oder doch nur 1byte.

    und vorallem wie sieht es dann im Speicher aus? Und wenn das der Fall ist, kann man den Computer "zwingen" das er nur die nötigen bytes reserviert?

    Hoffe ich habe mich einwenig verständlich ausgedrückt.

    Gruss und vielen Dank



  • und vorallem wie sieht es dann im Speicher aus? Und wenn das der Fall ist, kann man den Computer "zwingen" das er nur die nötigen bytes reserviert?

    wie es im Speicher aussieht kann dir niemand sagen 😉 - weil du mit logischen und nicht physikalischen Adressen arbeitest - um verstehen zu können was da abgeht müsstest du dich mit der Memory Mapping Unit beschäftigen - aber das ist gar nicht nötig

    such nach dem Stichwort Alignment 😉
    http://msdn2.microsoft.com/en-gb/library/2e70t5y1.aspx



  • Hi,

    ich würde Klassen sowieso nicht "binär auf die Reise schicken", sondern immer in ein Protokoll einpacken - und sei es noch sie klein und simpel. Also einfach eine "transformToMyProt()" und das Ergebnis in die API des "Verschickers" werfen.....

    • Damit ist man wenigstens compilerunabhängig (verschiedene Compiler(-einstellungen/-versionen/-...) können unterschiedliche Speicherlayouts haben),
    • plattformunabhängig (andere Maschinen, andere Sitten),
    • das funktioniert auch mit "Nicht-PODs" und
    • man ist nicht ganz so sensibel gegenüber Änderungen auf der anderen Seite (Dein Klassenlayout steckt vermutlich ziemlich tief in Deinem Programm; für eine Protokolländerung brauchst Du vermutlich nur die transformToMyProt()-Implementierung anzupassen.

    Gruß,

    Simon2.



  • Das wegen dem Speicher ist mir klar, eigentlich wollte ich wissen ob es einen Unterschied zwischen sizeof und Anzahl reservierter Speicher im System gibt.

    Also zum Bsp bei der Klasse point kann es möglich sein das man folgendes erhält:

    sizeof(point) = 19bytes
    tatsächliche speicherreservierung = 24bytes

    oder
    sizeof(point) = 19bytes
    tatsächliche speicherreservierung = 19bytes

    oder
    sizeof(point) = 24bytes
    tatsächliche speicherreservierung = 24bytes

    das meinte wie es im Speicher aussieht...

    -------------------------------------------------------------------------------
    Da ich für jedes Paket eine Klasse(Struct) vorgesehen(wie Point) bin ich eigentlich sehr flexibel was Protokollabänderungen betrifft. Ich muss nur meine Klasse(Struct) abändern und alles funktioniert gleich weiter, da ich hauptsächlich mit memcpy und sizeof arbeite.

    Jedenfalls sollte es das, kommt eben drauf an wie es mit der speicherreservierung aussieht 😞

    Gruss



  • flownfluid schrieb:

    ...
    Da ich für jedes Paket eine Klasse(Struct) vorgesehen(wie Point) bin ich eigentlich sehr flexibel was Protokollabänderungen betrifft. Ich muss nur meine Klasse(Struct) abändern und alles funktioniert gleich weiter, da ich hauptsächlich mit memcpy und sizeof arbeite....

    .. naja und jede Funktion (in jedem Modul), die Point sonst noch nutzen.
    Wenn Du Glück hast, reicht ein Recompile, aber der ist Minimum. Mit einer "transformToProt()"-Funktion würde ein Relink reichen (natürlich auch ein Compile des Implementationsmoduls von "transformToProt()", aber da braucht außer der Funktion ja nichts drinzustehen).
    Oder bei Verwendung einer dynamischen Bibliothek bräuchtest Du nur die neu zu linken könntest Du sogar im Laufenden Betrieb der "Hauptanwendung" eine Protokolländerung unterschieben.

    zu Deiner eigentlichen Frage schreibt der Standard:
    "(5.3.3.2) Sizeof
    ...When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objetcs of that type in an array..."
    D.h. Du bekommst mindestens den tatsächlichen Speicherbedarf (inkl. "internem Padding") Deines Objektes raus ... evtl. sogar noch einen Aufschlag, wenn ein nachfolgendes Objekt gleichen Typs nicht direkt dahinter plaziert werden würde.

    Gruß,

    Simon2.



  • Genau das ist ja mein Problem:

    evtl. sogar noch einen Aufschlag, wenn ein nachfolgendes Objekt gleichen Typs nicht direkt dahinter plaziert werden würde.

    Kann man nun das irgendwie verhinderen? So das es immer nur die minimale Anzahl Bytes braucht?



  • Du koenntest bei deinem Compiler das Alignment auf 1 Byte stellen, dann sind
    die Objekte immer ausgerichtet, ansonsten wird das Objekt von seiner Groesse,
    sofern es sich nicht um eine 2er Potenz handelt, auf die naechste 2er Potenz
    ausgerichtet.

    gruss
    v R



  • @flownfluid
    Wenn du MSVC verwendest dann mach das einfach so:

    #pragma pack(push)
    #pragma pack(1)
    struct BlaBlubb
    {
      //...
    };
    #pragma pack(pop)
    

    Dann "packt" der nur die structs(s) zwischen dem "#pragma pack(1)" und dem "#pragma pack(pop)". Ist IMHO besser, weil dann kann er sich weiterhin das Alignment aussuchen wie es sein sollte damit das Programm schnell läuft. Das ganze Programm mit "pack=1" zu compilieren ... würde ich nicht machen, ist ne unnötige Bremse.


Anmelden zum Antworten