Thread: data and struct alignment in windows...

  1. #1
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547

    data and struct alignment in windows...

    Had me a problem with Windows code that turned out to be an alignment problem... what a pain that was to figure out!

    Is there a standard alignment for windows structs and variables?

    I often use #pragma pack(1) with chunks that have to traverse the network and I'm wondering how unhappy I'm about to make myself...

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Alignment is compiler dependent. Avoid packing if not necessary; they're unportable and they can cause speed penalties (compilers insert padding for a reason).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Elysia View Post
    Alignment is compiler dependent. Avoid packing if not necessary; they're unportable and they can cause speed penalties (compilers insert padding for a reason).
    AND... as I recently learned, they can cause some totally bizarre errors... even cause programs to stop working.

    I'm not exactly a rookie at C and no beginner at programming but this one caught me totally off guard... All my registry access subroutines quit working, and I'd only applied the #pragma pack to 1 struct that does get sent out on the network to another machine...

    So last night I'm thinking ... "If that one little change can cause all that. How much trouble am I really in"...

    Thanks for the reply, Elysia. I should take it then, there's no hard and fast rule?

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Probably because you're trying to write the struct in binary format into the registry. That is, you simply copy all of the bytes it contains into the registry. Which, as you might understand, can cause some problems if the byte layout changes.
    You should really try to encapsulate/abstract the whole thing. That is, convert it to a common format, serialize, convert back. Work on a member-by-member basis. That's really only the safest way, which can be a pain in C.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    The rule of thumb for pretty much any C programming is to assume the functions take aligned data, unless whatever accompanying documentation says otherwise. The Windows function parameters which allow unaligned access have the UNALIGNED marker on MSDN. On Windows. depending on the architecture and app settings, unaligned accesses may do nothing, just be an order of magnitude slower, create bugs, or just crash the process.

    What Elysia says is true too, just blasting structures of native types around as a bunch of bits is asking for trouble especially if one destination is using a version of your program built with different compiler settings, on a different OS or on a different architecture.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by adeyblue View Post
    What Elysia says is true too, just blasting structures of native types around as a bunch of bits is asking for trouble especially if one destination is using a version of your program built with different compiler settings, on a different OS or on a different architecture.
    Quote Originally Posted by Elysia View Post
    Probably because you're trying to write the struct in binary format into the registry. That is, you simply copy all of the bytes it contains into the registry. Which, as you might understand, can cause some problems if the byte layout changes.
    You should really try to encapsulate/abstract the whole thing. That is, convert it to a common format, serialize, convert back. Work on a member-by-member basis. That's really only the safest way, which can be a pain in C.
    Thank you both for such well considered replies. As I say, this is the first time I've run into this one and it's still just a tad confusing for me...

    What basically happened is that a struct I was storing to registry stopped loading. SHGetValue would no longer read it and I was getting errors everytime I tried. However the problem was actually caused by another struct I already had in memory. The registry struct was being loaded into this other struct and the whole thing, in turn goes out to another machine for analysis... Then it just stopped working. Literally one minute, all is well, change one variable from word to byte and poof, nothing works anymore... 14 panic stricken hours later I discovered the alignment issue and had it fixed in just a very few minutes.

    I don't think there is an issue with transmitting binary data in this case because the software involved is maintained and distributed on the local area net as matched server/client pairs. Nobody else is making their own version clients to connect to my server (yet) so I'm hoping I'm good for the moment...

    90% of the stuff being sent back and forth is in formatted datagrams. PassCode, Command, Data... and mostly the data is either 1 or 2 bytes or short strings, depending on the command being processed. That has always been 100% reliable... so far. This one packet that messed me up is the only exception... it contains configuration information sent to clients as they make first contact with the server.

    This does however raise a significant concern about the communication between these softwares that I will have to address in some way... although the how of it is not obvious to me just yet.
    Last edited by CommonTater; 09-25-2010 at 11:32 AM.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Your software must agree on a common format, not just raw data. This is essential, especially due to padding. It would be the first step, I think. Make functions that can basically transform a struct into char array with data (which would individually convert each member of the struct), and vice versa.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Elysia View Post
    Your software must agree on a common format, not just raw data. This is essential, especially due to padding. It would be the first step, I think. Make functions that can basically transform a struct into char array with data (which would individually convert each member of the struct), and vice versa.
    I've got the internal structs all straightened out now (there were only 2, so it wasn't much of a problem). Now the stuff that has to travel by datagram...

    UDP datagrams are naturally byte arrays so converting from internal struct to one that overlays a blank datagram is pretty easy. This part has, in fact, been working perfectly from the beginning... so long as I give it good data to work with there's never been a miscommunication.

    For example:
    Code:
    #pragma pack(1)
    
    // datagram structure
    typedef struct tDATAGRAM
      { DWORD PassCode;               // Passcode
        TCHAR Guard1;                 // always 0
        BYTE  Command;                // command byte
        TCHAR Guard2;                 // always 0
        BYTE  Data[MAX_DGRAMDATA]; }  // data field
      DATAGRAM, *pDATAGRAM;    
    
    #pragma pack()
    This definition, as well as the definitions of structs to be transmitted, is globalized on both client and server. (same header file used on both)

    To send a datagram I overlay a struct or string on the Data field and, so far, no errors of any kind. Most of the structs being used are specific to this function... for example a packet to send the current system time is in a DG_TIME struct that is loaded from the windows time functions. I don't just send the windows time struct. The only case where I was loading a struct into memory and transmitting it directly was the one that tripped me up... the rest of it all seems to work well enough.

    But I do confess that my confidence in this is now rattled...

    So.. how worried should I be???

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Also consider that different platforms may have different sizes on types and different bit representation. One obvious difference that comes to mind is int. On Windows x64, it's 32 bits; on Linux, it's 64 bits. For example.
    To be safe and portable, you need to convert it to some fixed format which you control 100%.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    I see where you're heading now... I'm gonna have to give this some serious thought.

    Thank you for the help, it is greatly appreciated.

    (not that I expect this to ever be portable or ported code)
    Last edited by CommonTater; 09-25-2010 at 04:44 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  2. xor linked list
    By adramalech in forum C Programming
    Replies: 23
    Last Post: 10-14-2008, 10:13 AM
  3. Script errors - bool unrecognized and struct issues
    By ulillillia in forum Windows Programming
    Replies: 10
    Last Post: 12-18-2006, 04:44 AM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  5. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM