Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

11.07.2007, 21:28

[GELÖST] Strukturgrößenunterschiede --> Problem

Hi Leute

Ich schreibe gerade ein Server- und ein ClientProgramm.
Beide nutzen die selbe Headerdatei in der folgende Struktur def. ist:

Quellcode

1
2
3
4
5
6
struct MsgNewServer {
    char achName[16];   //sizeof()=16
    char achIP[15];   //sizeof()=15
    unsigned short usPort;   //sizeof()=2
    ServerType Type;   //sizeof()=4
};


ich will diese Struktur vom Server zum Client senden.

Leider funzt es nicht weil

Quellcode

1
sizeof(MsgNewServer )


die Größe 40 im Server ergibt und 37 beim Client!!!
Ich habe natürlich alle Größen innerhalb der Struktur geprüft und sie sind bei BEIDEN alle gleich! Trotzdem ergibt die Gesamtgröße beim Server 40, obwohl sie 37 sein sollte!

Der Hammer ist, dass wenn ich die Struktur ändere zu:

Quellcode

1
2
3
4
5
6
struct MsgNewServer {
    char achName[19];//19
    char achIP[15];//15
    unsigned short usPort;//2
    ServerType Type;//4
};


dann ergibt sie bei beiden Programmen 40!

ändere ich die Strukur zu:

Quellcode

1
2
3
4
5
6
struct MsgNewServer {
    char achName[20];//20
    char achIP[15];//15
    unsigned short usPort;//2
    ServerType Type;//4
};


so ist die Größe beim Server 44 und beim Client 41!

Der Client ist übrigens eine WIN32 Anwendung, während der Server ein Konsolenprog. ist, sonst ist bei der Erstellung in VS05 Pro kein Unterschied gewesen!

Ich bin mir ziemlich sicher dass es ein Compilerproblem ist, doch hab leider keine Ahnung was genau!

mfg Markus

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

2

11.07.2007, 21:30

versuchs mal mit

C-/C++-Quelltext

1
2
3
4
5
6
7
8
#pragma pack(push, 1)
struct MsgNewServer {
   char achName[16];   //sizeof()=16

   char achIP[15];   //sizeof()=15

   unsigned short usPort;   //sizeof()=2

   ServerType Type;   //sizeof()=4

};
#pragma pack(pop)


Zitat von »"RakNet Doku"«

Noticed the #pragma pack(push,1) and #pragma pack(pop) ? These force your compiler (in this case VC++), to pack the structure as byte-aligned. Check your compiler documentation to learn more.

3

11.07.2007, 21:50

Danke!

Funzt jetzt alles perfekt! Richtig ärgerlich 6 Stunden einen Fehler zu suchen und dann eine solch einfach Antwort zu erhalten :evil: :D

Hab in den Projekteigenschaften auf ein Byte gestellt! Es war auf 4 gesetzt :oops: Muss ich übersehen haben!

mfg Markus

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

4

11.07.2007, 21:59

Ja nervig sowas :) Gehts jetzt auch ohne die präprozessor direktiven?

ChrisJ

Alter Hase

Beiträge: 487

Wohnort: Schweich

Beruf: Schüler

  • Private Nachricht senden

5

11.07.2007, 22:01

einige prozessoren adressieren variablen 4-byte aligned, wodurch sich die größen der strukturen ändern können.

C-/C++-Quelltext

1
2
3
4
5
struct
{
char foo;
int bar;
};


kann auf einigen prozessoren größer sein als

C-/C++-Quelltext

1
2
3
4
5
struct
{
int bar;
char foo;
};
"Don't trust your eyes: They are a hell of a lot smarter than you are"

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

11.07.2007, 23:19

das liegt in erster linie nicht am prozessor, sondern am compiler. der grund dafür ist, dass der prozessor schneller auf member zugreifen kann, wenn diese richtig aligned sind (also das struct entsprechend gepadded ist). deswegen ist es auch net unbedingt eine gute idee in den projekteinstellungen gleich mal global ein anderes packing einzustellen. manchmal macht es sinn, aber generell sollte man dem compiler überlassen wie er das macht...

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

12.07.2007, 10:46

Naja. Man kann sowas vermeiden durch geschicktes Design. Ein Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Paket
{
    char* daten;
    DWORD *ItemID;  

public: 
    uLong alderCheck;
    Code code;
    size_t ZippedSize, realsize;
    unsigned short MSG, NumIDs;
[...]

    inline void ReadHeader(char* d)
    {
        delete[] daten;
        daten = NULL;
        delete[] ItemID;
        ItemID = NULL;

        size_t offset;
        memcpy(&alderCheck, d, sizeof(uLong));                      offset = sizeof(uLong);
        memcpy(&code, d + offset, sizeof(Code));                    offset += sizeof(Code);
        memcpy(&ZippedSize, d + offset, sizeof(size_t));            offset += sizeof(size_t);
        memcpy(&realsize, d + offset, sizeof(size_t));              offset += sizeof(size_t);
        memcpy(&MSG, d + offset, sizeof(unsigned short));           offset += sizeof(unsigned short);
        memcpy(&NumIDs, d + offset, sizeof(unsigned short));        offset += sizeof(unsigned short);

        if(NumIDs)
        {
            ItemID  = new DWORD[NumIDs];
            memset(ItemID, 0, NumIDs * sizeof(DWORD));
        }

    }

    inline void WriteHeader(char* d)
    {
        ComputeAlder();

        size_t offset;
        memcpy(d, &alderCheck, sizeof(uLong));                      offset = sizeof(uLong);
        memcpy(d + offset, &code, sizeof(Code));                    offset += sizeof(Code);
        memcpy(d + offset, &ZippedSize,sizeof(size_t));             offset += sizeof(size_t);
        memcpy(d + offset, &realsize, sizeof(size_t));              offset += sizeof(size_t);
        memcpy(d + offset, &MSG, sizeof(unsigned short));           offset += sizeof(unsigned short);
        memcpy(d + offset, &NumIDs, sizeof(unsigned short));        offset += sizeof(unsigned short);
        memcpy(d + offset, ItemID, NumIDs * sizeof(DWORD));
    }
[...]
};
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

8

12.07.2007, 11:12

Naja, geschicktes Design? Das ist ungleich mehr Tipparbeit und zudem auch noch recht unschön. Was wenn z.B. Code auch eine Struktur ist? Muss ich dann erst nen Puffer anlegen, für die Struktur ReadXYZ aufrufen und den Puffer dann kopieren? Schön ist das nicht und die gewonnene "Effizienz" geht dadurch auch wieder verloren.

Übrigens:
Methodendefinitionen in der Klassendefinition sind automatisch inline und ReadHeader sollte ein const char* erwarten.
@D13_Dreinig

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

12.07.2007, 11:22

ich denke die sauberste lösung ist in dem fall die über pragmas.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

10

12.07.2007, 11:45

Code ist ein enum und mit const correctness habe ich es nicht so :D
Bei der Lösung kann man immerhin gezielt einzelne Felder einer Struktur/Klasse auslassen und das mit dem Tippen ist dank C&P kein Ding^^. Also meine persönliche Erfahrung haben gezeigt, dass es mit dem direkten kopieren von struct/class so eine Sache ist. Daher nutzen wir das System und sind damit bis jetzt ganz gut zurecht gekommen.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Werbeanzeige