Structure alignment struggle.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • A n g l e r

    Structure alignment struggle.

    Hi all.


    I've got the following code as a part of managed C++ library that is
    loaded by a project in C#:

    public ref class FlyCaptureEnums AndStructsManag ed
    {
    public:
    typedef enum class FlyCaptureCamer aModel { blabla, blabla2 };
    typedef enum class FlyCaptureCamer aType { blabla, blablabla, blamax =
    0x7FFFFFFF };

    [StructLayout(La youtKind::Expli cit, Pack=1 Size=2028)]
    typedef ref struct FlyCaptureInfoE x
    {
    [FieldOffset(0)] int SerialNumber;
    [FieldOffset(4)] FlyCaptureCamer aType CameraType;
    [FieldOffset(8)] FlyCaptureCamer aModel CameraModel;
    [FieldOffset(12) , MarshalAs(Unman agedType::ByVal TStr, SizeConst=512)]
    String^ pszModelName;

    ... blablabla
    };
    };

    Now, I'm facing some alignment issue after this has been ported to x64
    platform. I used to work with windows x86 and VS 2005, now am working
    with VS 2008 and XP x64.

    It looks that the offset FieldOffset(12) is for some reason treated as
    an inappropriate layout as raised exceptions indicate this clearly. When
    It definitely helps when I amend the offset position to FieldOffset(16) .
    I'm a bit puzzled cos I've tried to force alignment with Pack=1 and
    Pack=4, though it still acts like it was specified Pack=8.

    Just to stress out as well that the same structure built directly in C#
    (even without specifying the pack size) seems to have the desired 4 byte
    layout.


    Do you have any clue what is going on here? Perhaps this all is down to
    some compiler switches?


    Thanks a lot,
    Peter.
  • Jeff Winn

    #2
    Re: Structure alignment struggle.

    It would have helped a lot more if you hadn't removed part of the struct
    definition.

    I'm having a bit of trouble understanding why you're explicitly defining the
    field offsets for the types involved. You've manually specified the
    locations where they would be at normally simply using a sequential layout,
    but I can't tell for sure since you decided to partially show us the struct.

    Also according to the docs (unless I'm interpreting them incorrectly), the
    pack property only works when you've specified Sequential for the layout.


    What you've shown us the equivalent of: I have a problem with this method,
    it's throwing an object null reference exception. Why?
    void DoSomething() {
    int x = 0;
    ...
    }

    "A n g l e r" <p|k|o|n|i|u|s| z@h-o-t-m-a-i-l.c_o_mwrote in message
    news:g3p8v2$l8k $1@news.onet.pl ...
    Hi all.
    >
    >
    I've got the following code as a part of managed C++ library that is
    loaded by a project in C#:
    >
    public ref class FlyCaptureEnums AndStructsManag ed
    {
    public:
    typedef enum class FlyCaptureCamer aModel { blabla, blabla2 };
    typedef enum class FlyCaptureCamer aType { blabla, blablabla, blamax =
    0x7FFFFFFF };
    >
    [StructLayout(La youtKind::Expli cit, Pack=1 Size=2028)]
    typedef ref struct FlyCaptureInfoE x
    {
    [FieldOffset(0)] int SerialNumber;
    [FieldOffset(4)] FlyCaptureCamer aType CameraType;
    [FieldOffset(8)] FlyCaptureCamer aModel CameraModel; [FieldOffset(12) ,
    MarshalAs(Unman agedType::ByVal TStr, SizeConst=512)] String^ pszModelName;
    >
    ... blablabla
    };
    };
    >
    Now, I'm facing some alignment issue after this has been ported to x64
    platform. I used to work with windows x86 and VS 2005, now am working with
    VS 2008 and XP x64.
    >
    It looks that the offset FieldOffset(12) is for some reason treated as an
    inappropriate layout as raised exceptions indicate this clearly. When It
    definitely helps when I amend the offset position to FieldOffset(16) . I'm
    a bit puzzled cos I've tried to force alignment with Pack=1 and Pack=4,
    though it still acts like it was specified Pack=8.
    >
    Just to stress out as well that the same structure built directly in C#
    (even without specifying the pack size) seems to have the desired 4 byte
    layout.
    >
    >
    Do you have any clue what is going on here? Perhaps this all is down to
    some compiler switches?
    >
    >
    Thanks a lot,
    Peter.

    Comment

    • =?ISO-8859-2?Q?G=F6ran_Andersson?=

      #3
      Re: Structure alignment struggle.

      A n g l e r wrote:
      Hi all.
      >
      >
      I've got the following code as a part of managed C++ library that is
      loaded by a project in C#:
      >
      public ref class FlyCaptureEnums AndStructsManag ed
      {
      public:
      typedef enum class FlyCaptureCamer aModel { blabla, blabla2 };
      typedef enum class FlyCaptureCamer aType { blabla, blablabla, blamax
      = 0x7FFFFFFF };
      >
      [StructLayout(La youtKind::Expli cit, Pack=1 Size=2028)]
      typedef ref struct FlyCaptureInfoE x
      {
      [FieldOffset(0)] int SerialNumber;
      [FieldOffset(4)] FlyCaptureCamer aType CameraType;
      [FieldOffset(8)] FlyCaptureCamer aModel CameraModel;
      [FieldOffset(12) , MarshalAs(Unman agedType::ByVal TStr,
      SizeConst=512)] String^ pszModelName;
      What do you have here? What is the FielfOffset of the next member?

      In x64, the pointers are 8 bytes instead of 4 bytes. If you have placed
      the next member at 16, the pointer would overlap it.
      ... blablabla
      };
      };
      >
      Now, I'm facing some alignment issue after this has been ported to x64
      platform. I used to work with windows x86 and VS 2005, now am working
      with VS 2008 and XP x64.
      >
      It looks that the offset FieldOffset(12) is for some reason treated as
      an inappropriate layout as raised exceptions indicate this clearly. When
      It definitely helps when I amend the offset position to FieldOffset(16) .
      I'm a bit puzzled cos I've tried to force alignment with Pack=1 and
      Pack=4, though it still acts like it was specified Pack=8.
      >
      Just to stress out as well that the same structure built directly in C#
      (even without specifying the pack size) seems to have the desired 4 byte
      layout.
      >
      >
      Do you have any clue what is going on here? Perhaps this all is down to
      some compiler switches?
      >
      >
      Thanks a lot,
      Peter.

      --
      Göran Andersson
      _____
      Göran Anderssons privata hemsida.

      Comment

      • A n g l e r

        #4
        Re: Structure alignment struggle.

        I'm having a bit of trouble understanding why you're explicitly defining
        the field offsets for the types involved. You've manually specified the
        locations where they would be at normally simply using a sequential
        layout, but I can't tell for sure since you decided to partially show us
        the struct.
        Well, I've just replaced this all with Sequential and now it turns out
        to work fine. The reason why I have it declared likewise is that
        Sequential layout didn't seem to work fine on my previous machine and VS
        2005 :d I have no clue what was the reason.
        Also according to the docs (unless I'm interpreting them incorrectly),
        the pack property only works when you've specified Sequential for the
        layout.
        http://msdn.microsoft.com/en-us/libr...bute.pack.aspx
        Yep, you're right. I've also spotted this. Any reason why Explicit
        layout doesn't work as aligned every 4 bytes on x64?

        Thanks,
        Peter

        Comment

        • A n g l e r

          #5
          Re: Structure alignment struggle.

          What do you have here? What is the FielfOffset of the next member?
          >
          In x64, the pointers are 8 bytes instead of 4 bytes. If you have placed
          the next member at 16, the pointer would overlap it.

          Erm, first three fields aren't pointers. The forth one has to do with
          pointers, though I don't get why it needs to be aligned every 8 bytes
          unless it's actual position is calculated with respect to the end of the
          structure rather than the beginning. Perhaps I misapprehend some aspects
          of this sort of layout, though Sequential doesn't force me to have 8
          bytes alignment and works fine ... So, what is the little trick in it?

          Cheers,
          Peter.

          Comment

          • Jeff Winn

            #6
            Re: Structure alignment struggle.

            Explictly defining the layout for members of structures determine where in
            the structs the members get serialized based on the position from the start
            of the struct. Also, FYI, you don't need to specify sequential for the
            layout since it's the default setting for structs.

            [StructLayout(La youtKind.Explic it)]
            struct MyStruct {
            [FieldOffset(0)]
            public int A;

            [FieldOffset(4)]
            public int B;

            [FieldOffset(8)]
            public IntPtr C;

            [FieldOffset(12)]
            public int D;
            }

            The Int32 type is 4 bytes wide, which is why the offset is 4 bytes apart.
            However, since the C member is a pointer - on a 32 bit system this would be
            4 bytes wide, whereas on a 64 bit system it is 8 bytes wide. So, if you're
            explicitly defining the field positions and you move the application to a 64
            bit system you can see that D would be in the wrong position as it would
            actually need to be at offset 16.

            Glad you got everything working. Happy to help :)

            "A n g l e r" <p|k|o|n|i|u|s| z@h-o-t-m-a-i-l.c_o_mwrote in message
            news:g3pda1$u1u $1@news.onet.pl ...
            >
            >What do you have here? What is the FielfOffset of the next member?
            >>
            >In x64, the pointers are 8 bytes instead of 4 bytes. If you have placed
            >the next member at 16, the pointer would overlap it.
            >
            >
            Erm, first three fields aren't pointers. The forth one has to do with
            pointers, though I don't get why it needs to be aligned every 8 bytes
            unless it's actual position is calculated with respect to the end of the
            structure rather than the beginning. Perhaps I misapprehend some aspects
            of this sort of layout, though Sequential doesn't force me to have 8 bytes
            alignment and works fine ... So, what is the little trick in it?
            >
            Cheers,
            Peter.

            Comment

            • A n g l e r

              #7
              Re: Structure alignment struggle.

              Jeff, yes, though this still doesn't answer my question which is why
              Sequential offset doesn't require such alignment? What is the actual
              difference in representing both types of structures on a system level?

              Cheers,
              P.
              Explictly defining the layout for members of structures determine where
              in the structs the members get serialized based on the position from the
              start of the struct. Also, FYI, you don't need to specify sequential for
              the layout since it's the default setting for structs.
              >
              [StructLayout(La youtKind.Explic it)]
              struct MyStruct {
              [FieldOffset(0)]
              public int A;
              >
              [FieldOffset(4)]
              public int B;
              >
              [FieldOffset(8)]
              public IntPtr C;
              >
              [FieldOffset(12)]
              public int D;
              }
              >
              The Int32 type is 4 bytes wide, which is why the offset is 4 bytes
              apart. However, since the C member is a pointer - on a 32 bit system
              this would be 4 bytes wide, whereas on a 64 bit system it is 8 bytes
              wide. So, if you're explicitly defining the field positions and you move
              the application to a 64 bit system you can see that D would be in the
              wrong position as it would actually need to be at offset 16.

              Comment

              • =?ISO-8859-2?Q?G=F6ran_Andersson?=

                #8
                Re: Structure alignment struggle.

                A n g l e r wrote:
                >
                >What do you have here? What is the FielfOffset of the next member?
                >>
                >In x64, the pointers are 8 bytes instead of 4 bytes. If you have
                >placed the next member at 16, the pointer would overlap it.
                >
                >
                Erm, first three fields aren't pointers. The forth one has to do with
                pointers, though I don't get why it needs to be aligned every 8 bytes
                unless it's actual position is calculated with respect to the end of the
                structure rather than the beginning. Perhaps I misapprehend some aspects
                of this sort of layout, though Sequential doesn't force me to have 8
                bytes alignment and works fine ... So, what is the little trick in it?
                >
                Cheers,
                Peter.
                The third member isn't a pointer? I don't do any development in C++
                these days, so I don't know exactly what the types translates into...

                You are mixing layout attributes with marshalling attributes, perhaps
                that's the problem? Layout attributes are used by the CLR to layout the
                managed data, while marshalling attributes are used by the marshalling
                methods when the data is copied into an unmanaged data structure.

                --
                Göran Andersson
                _____
                Göran Anderssons privata hemsida.

                Comment

                • A n g l e r

                  #9
                  Re: Structure alignment struggle.

                  The third member isn't a pointer? I don't do any development in C++
                  these days, so I don't know exactly what the types translates into...
                  The forth one from my example is pointer - at least as long as I'm of a
                  sound mind ;)
                  You are mixing layout attributes with marshalling attributes, perhaps
                  that's the problem? Layout attributes are used by the CLR to layout the
                  managed data, while marshalling attributes are used by the marshalling
                  methods when the data is copied into an unmanaged data structure.
                  Erm, ok, though this seems to be a sleek way of passing unmanaged
                  structure with strings to C# environment ...

                  Comment

                  • Jeff Winn

                    #10
                    Re: Structure alignment struggle.

                    There is no difference in the structure itself, the difference is how the
                    marshaller handles the struct. When the members are laid out sequentially
                    (LayoutKind.Seq uential) you're telling .NET to handle the marshalling for
                    you for that struct. It will determine where the members need to go when
                    it's marshalling them back and forth. If you're using an explicit layout
                    with field offsets for the members, you're telling the marshaller where it
                    should look for the data.

                    This would be what the struct looks like on a 32 bit system.

                    A B C D
                    00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
                    0 4 8 12

                    And this would be the same struct represented on a 64 bit system.

                    A B C
                    D
                    00 00 00 00 | 00 00 00 00 | 00 00 00 00 00 00 00 00 | 00 00 00 00
                    0 4 8 -12-
                    16

                    With the example I wrote earlier, it's basically telling the marshaller to
                    look for the D field at position 12 of the array, which would be the last 4
                    bytes of the pointer used by the C field. I've rarely needed to use an
                    explicit layout for a struct. If I remember the last time I needed one I was
                    having to store 2 different objects at the same position within the struct.
                    Probably was from a union inside the struct defintion I was using in the
                    Win32 API.

                    Generally speaking you shouldn't use explicit layouts unless you absolutely
                    have to. They can cause a lot of problems when using different platforms.

                    "A n g l e r" <p|k|o|n|i|u|s| z@h-o-t-m-a-i-l.c_o_mwrote in message
                    news:g3qe18$62o $1@news.onet.pl ...
                    Jeff, yes, though this still doesn't answer my question which is why
                    Sequential offset doesn't require such alignment? What is the actual
                    difference in representing both types of structures on a system level?
                    >
                    Cheers,
                    P.
                    >
                    >Explictly defining the layout for members of structures determine where
                    >in the structs the members get serialized based on the position from the
                    >start of the struct. Also, FYI, you don't need to specify sequential for
                    >the layout since it's the default setting for structs.
                    >>
                    >[StructLayout(La youtKind.Explic it)]
                    >struct MyStruct {
                    > [FieldOffset(0)]
                    > public int A;
                    >>
                    > [FieldOffset(4)]
                    > public int B;
                    >>
                    > [FieldOffset(8)]
                    > public IntPtr C;
                    >>
                    > [FieldOffset(12)]
                    > public int D;
                    >}
                    >>
                    >The Int32 type is 4 bytes wide, which is why the offset is 4 bytes apart.
                    >However, since the C member is a pointer - on a 32 bit system this would
                    >be 4 bytes wide, whereas on a 64 bit system it is 8 bytes wide. So, if
                    >you're explicitly defining the field positions and you move the
                    >application to a 64 bit system you can see that D would be in the wrong
                    >position as it would actually need to be at offset 16.

                    Comment

                    Working...