#pragma pack(push, 4) (msvc) question

Hi guys,

First post here, great group (been reading it for the last month), and
the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way MSVC
build DLL and MINGW one can get exchanged. I don’t have any other means of
detecting how the actual DLL was compiled.

It’s not a big deal, but if this pragma is no longer needed what would be
the cost of removing it?

[1] - http://luajit.org/ext_ffi_**tutorial.htmlhttp://luajit.org/ext_ffi_tutorial.html

diff -r 9269bf952041 include/begin_code.h
— a/include/begin_code.h Sat Aug 06 02:15:23 2011 -0400
+++ b/include/begin_code.h Fri Aug 12 16:08:32 2011 -0700
@@ -87,7 +87,7 @@
#ifdef BORLANDC
#pragma nopackwarning
#endif
-#pragma pack(push,4)
+//#pragma pack(push,4)
#endif /* Compiler needs structure packing set */

/* Set up compiler-specific options for inlining functions /
diff -r 9269bf952041 include/close_code.h
— a/include/close_code.h Sat Aug 06 02:15:23 2011 -0400
+++ b/include/close_code.h Fri Aug 12 16:08:32 2011 -0700
@@ -33,5 +33,5 @@
#ifdef BORLANDC
#pragma nopackwarning
#endif
-#pragma pack(pop)
+//#pragma pack(pop)
#endif /
Compiler needs structure packing set */

Thanks,
Dimiter ‘malkia’ Stanev.

It’s a compatibility thing. Lets say you have a file with a header, you
define a struct for the header. If you wanna just fread() the struct
rather reading it an entry at a time and assigning it to a struct, you
make sure the struct alignment matches the file header alignments.

If SDL is assuming that structures across shared memory spaces or
certain files have a 4 byte alignment, then they really need to be kept
that way, otherwise you’ll possibly break things.

Different compilers have different ways of specifying struct / etc
alignment within source files. Some don’t even use #pragma for it :slight_smile:

-WillOn 8/15/2011 3:53 PM, malkia wrote:

Hi guys,

First post here, great group (been reading it for the last month),
and the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way
MSVC build DLL and MINGW one can get exchanged. I don’t have any other
means of detecting how the actual DLL was compiled.

It’s not a big deal, but if this pragma is no longer needed what
would be the cost of removing it?

Hi guys,

First post here, great group (been reading it for the last month), and
the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way MSVC
build DLL and MINGW one can get exchanged. I don’t have any other means of
detecting how the actual DLL was compiled.

It’s not a big deal, but if this pragma is no longer needed what would
be the cost of removing it?

It’s a compatibility thing. Lets say you have a file with a header, you
define a struct for the header. If you wanna just fread() the struct rather
reading it an entry at a time and assigning it to a struct, you make sure
the struct alignment matches the file header alignments.

Well, sort of…if you are just fwrite()/fread()'ing a struct ot/from disk,
you get what you deserve, which is a slap to the face.

If SDL is assuming that structures across shared memory spaces or certain
files have a 4 byte alignment, then they really need to be kept that way,
otherwise you’ll possibly break things.

Different compilers have different ways of specifying struct / etc
alignment within source files. Some don’t even use #pragma for it :slight_smile:

-Will

To elaborate on that…

The pragmas are there on MSVC to set the internal alignment of structure
members. It is possible to change the default values of these using MSVC
with the /Zpxx option, e.g: /Zp16 to set 16-byte member alignment. This
option* overrides it and specifies that SDL’s structures are* 4 byte
aligned. This actually increases compatibility since nobody can build/ship
DLLs with incompatible structure alignment/size, regardless of what they
specify on the command line. Similarly, if your app is built using /Zp8 and
you include SDL’s headers, you don’t want it to mysteriously break because
your SDL library has 4-byte aligned structures and your app has 8-byte
aligned structures – you expect SDL “just work” and not to have to
recompile all of SDL just because you set /Zp8. So, removing it is actually
a bad idea if you want to maintain compatibility since then the sizeof() SDL
structures depends on what command line flags the user specifies when
building their app.

PatrickOn Mon, Aug 15, 2011 at 4:06 PM, William Langford wrote:

On 8/15/2011 3:53 PM, malkia wrote:

Computers like data to be nicely aligned so it can be accessed easily. As a
result the compiler will insert empty space between structure members if
they are not “packed”. Say a char (1) between two doubles (8) will end up
will 7 bytes of free space after it so it aligns!
That’s as far as I understand things anyway. The pragma macro takes car of
packing for you. Not sure about the args though…

William

Hi guys,

First post here, great group (been reading it for the last month), and
the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way MSVC
build DLL and MINGW one can get exchanged. I don’t have any other means
of

detecting how the actual DLL was compiled.

It’s not a big deal, but if this pragma is no longer needed what would
be the cost of removing it?

It’s a compatibility thing. Lets say you have a file with a header, you
define a struct for the header. If you wanna just fread() the struct
rather

reading it an entry at a time and assigning it to a struct, you make sure
the struct alignment matches the file header alignments.

Well, sort of…if you are just fwrite()/fread()'ing a struct ot/from
disk,
you get what you deserve, which is a slap to the face.

If SDL is assuming that structures across shared memory spaces or certain
files have a 4 byte alignment, then they really need to be kept that way,
otherwise you’ll possibly break things.

Different compilers have different ways of specifying struct / etc
alignment within source files. Some don’t even use #pragma for it :slight_smile:

-Will

To elaborate on that…

The pragmas are there on MSVC to set the internal alignment of structure
members. It is possible to change the default values of these using MSVC
with the /Zpxx option, e.g: /Zp16 to set 16-byte member alignment. This
option* overrides it and specifies that SDL’s structures are* 4 byte
aligned. This actually increases compatibility since nobody can build/ship
DLLs with incompatible structure alignment/size, regardless of what they
specify on the command line. Similarly, if your app is built using /Zp8
and
you include SDL’s headers, you don’t want it to mysteriously break because
your SDL library has 4-byte aligned structures and your app has 8-byte
aligned structures – you expect SDL “just work” and not to have to
recompile all of SDL just because you set /Zp8. So, removing it is
actually
a bad idea if you want to maintain compatibility since then the sizeof()
SDLOn 16 Aug 2011 07:27, “Patrick Baggett” <baggett.patrick at gmail.com> wrote:
On Mon, Aug 15, 2011 at 4:06 PM, William Langford wrote:

On 8/15/2011 3:53 PM, malkia wrote:
structures depends on what command line flags the user specifies when
building their app.

Patrick

My problem is that packing is done for MSVC compilers, but not for
others. Hence my bindings would only work with MSVC compiled DLL.
That’s perfectly fine, but I don’t have way to detect that (unless SDL
exports DEFINES - which now is too much)

Or for example the same binding, structure wise won’t work for Linux,
and others, and that’s perfectly legal, but I wish if it was not the
case. And SDL is already taking some care in that direction for the
events and WMInfo packing different variants in union.

Another solution is to create for each structure accessor method - this
would increase the API though (a bit like pixman, cairo, and other gnome
libs).

Personally I would just manually align anything up to 64-bit, and worry
about 128-bit later (it might come someday :)).

For example:

uint32 something;
void* pointer;

could be better:

uint32 something;
uint32 padding;
void* pointer;

Even if it’s done for the 32-bit code (unless SDL structures are used
quite a lot, but even then - they are probably not the most memory
efficient representation anyway to begin with).On 8/15/2011 4:37 PM, William Dyce wrote:

Computers like data to be nicely aligned so it can be accessed easily.
As a result the compiler will insert empty space between structure
members if they are not “packed”. Say a char (1) between two doubles (8)
will end up will 7 bytes of free space after it so it aligns!
That’s as far as I understand things anyway. The pragma macro takes car
of packing for you. Not sure about the args though…

William

On 16 Aug 2011 07:27, “Patrick Baggett” <baggett.patrick at gmail.com <mailto:baggett.patrick at gmail.com>> wrote:

On Mon, Aug 15, 2011 at 4:06 PM, William Langford <unfies at gmail.com <mailto:unfies at gmail.com>> wrote:

On 8/15/2011 3:53 PM, malkia wrote:

Hi guys,

First post here, great group (been reading it for the last month), and
the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way MSVC
build DLL and MINGW one can get exchanged. I don’t have any other
means of

detecting how the actual DLL was compiled.

It’s not a big deal, but if this pragma is no longer needed what would
be the cost of removing it?

It’s a compatibility thing. Lets say you have a file with a header, you
define a struct for the header. If you wanna just fread() the struct
rather

reading it an entry at a time and assigning it to a struct, you make
sure

the struct alignment matches the file header alignments.

Well, sort of…if you are just fwrite()/fread()'ing a struct
ot/from disk,
you get what you deserve, which is a slap to the face.

If SDL is assuming that structures across shared memory spaces or
certain

files have a 4 byte alignment, then they really need to be kept that
way,

otherwise you’ll possibly break things.

Different compilers have different ways of specifying struct / etc
alignment within source files. Some don’t even use #pragma for it :slight_smile:

-Will

To elaborate on that…

The pragmas are there on MSVC to set the internal alignment of structure
members. It is possible to change the default values of these using MSVC
with the /Zpxx option, e.g: /Zp16 to set 16-byte member alignment. This
option* overrides it and specifies that SDL’s structures are* 4 byte
aligned. This actually increases compatibility since nobody can
build/ship
DLLs with incompatible structure alignment/size, regardless of what they
specify on the command line. Similarly, if your app is built using
/Zp8 and
you include SDL’s headers, you don’t want it to mysteriously break
because
your SDL library has 4-byte aligned structures and your app has 8-byte
aligned structures – you expect SDL “just work” and not to have to
recompile all of SDL just because you set /Zp8. So, removing it is
actually
a bad idea if you want to maintain compatibility since then the
sizeof() SDL
structures depends on what command line flags the user specifies when
building their app.

Patrick


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

My own approach to all struct loading from disk is to use an unsigned char * and macros that read various type sizes from such a byte array with the proper endian order (for example d[0] + d[1] * 256

  • d[2] * 65536 + d[3] * 16777216 is a way to load little endian, regardless of architecture the code is running on), assigning to the structs (which may be packed any way the compiler pleases), and
    this solves both endian problems and alignment problems.

This means that I can load any file format on any architecture without worries, and can load to different struct formats if I so desire (for example my memory structs often have additional derived
data I calculate after reading in the disk data).

It’s important to understand that misaligned memory access is a crash on many architectures, and runs slower on the rest, so direct memory loading of structs is “highly unwise” to put it mildly, the
problem goes far beyond mere endian swapping.

Even on x86, you can get a crash if you use __m128 (SSE 128bit vector register) at misaligned addresses - although in that case you must also allocate your memory with memalign because malloc won’t
align to 16 byte by default.On 08/15/2011 05:05 PM, Dimiter ‘malkia’ Stanev wrote:

My problem is that packing is done for MSVC compilers, but not for others. Hence my bindings would only work with MSVC compiled DLL.
That’s perfectly fine, but I don’t have way to detect that (unless SDL exports DEFINES - which now is too much)

Or for example the same binding, structure wise won’t work for Linux, and others, and that’s perfectly legal, but I wish if it was not the case. And SDL is already taking some care in that direction
for the events and WMInfo packing different variants in union.

Another solution is to create for each structure accessor method - this would increase the API though (a bit like pixman, cairo, and other gnome libs).

Personally I would just manually align anything up to 64-bit, and worry about 128-bit later (it might come someday :)).

For example:

uint32 something;
void* pointer;

could be better:

uint32 something;
uint32 padding;
void* pointer;

Even if it’s done for the 32-bit code (unless SDL structures are used quite a lot, but even then - they are probably not the most memory efficient representation anyway to begin with).

On 8/15/2011 4:37 PM, William Dyce wrote:

Computers like data to be nicely aligned so it can be accessed easily.
As a result the compiler will insert empty space between structure
members if they are not “packed”. Say a char (1) between two doubles (8)
will end up will 7 bytes of free space after it so it aligns!
That’s as far as I understand things anyway. The pragma macro takes car
of packing for you. Not sure about the args though…

William

On 16 Aug 2011 07:27, “Patrick Baggett” <baggett.patrick at gmail.com <mailto:baggett.patrick at gmail.com>> wrote:

On Mon, Aug 15, 2011 at 4:06 PM, William Langford <unfies at gmail.com <mailto:unfies at gmail.com>> wrote:

On 8/15/2011 3:53 PM, malkia wrote:

Hi guys,

First post here, great group (been reading it for the last month), and
the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way MSVC
build DLL and MINGW one can get exchanged. I don’t have any other
means of

detecting how the actual DLL was compiled.

It’s not a big deal, but if this pragma is no longer needed what would
be the cost of removing it?

It’s a compatibility thing. Lets say you have a file with a header, you
define a struct for the header. If you wanna just fread() the struct
rather

reading it an entry at a time and assigning it to a struct, you make
sure

the struct alignment matches the file header alignments.

Well, sort of…if you are just fwrite()/fread()'ing a struct
ot/from disk,
you get what you deserve, which is a slap to the face.

If SDL is assuming that structures across shared memory spaces or
certain

files have a 4 byte alignment, then they really need to be kept that
way,

otherwise you’ll possibly break things.

Different compilers have different ways of specifying struct / etc
alignment within source files. Some don’t even use #pragma for it :slight_smile:

-Will

To elaborate on that…

The pragmas are there on MSVC to set the internal alignment of structure
members. It is possible to change the default values of these using MSVC
with the /Zpxx option, e.g: /Zp16 to set 16-byte member alignment. This
option* overrides it and specifies that SDL’s structures are* 4 byte
aligned. This actually increases compatibility since nobody can
build/ship
DLLs with incompatible structure alignment/size, regardless of what they
specify on the command line. Similarly, if your app is built using
/Zp8 and
you include SDL’s headers, you don’t want it to mysteriously break
because
your SDL library has 4-byte aligned structures and your app has 8-byte
aligned structures – you expect SDL “just work” and not to have to
recompile all of SDL just because you set /Zp8. So, removing it is
actually
a bad idea if you want to maintain compatibility since then the
sizeof() SDL
structures depends on what command line flags the user specifies when
building their app.

Patrick


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier

Hi Hale,

It’s important to understand that misaligned memory access is a crash on
many architectures, and runs slower on the rest, so direct memory
loading of structs is “highly unwise” to put it mildly, the problem goes
far beyond mere endian swapping.

I perfectly understand that. Spend few years writing IOP code for the PS2

Even on x86, you can get a crash if you use __m128 (SSE 128bit vector
register) at misaligned addresses - although in that case you must also
allocate your memory with memalign because malloc won’t align to 16 byte
by default.

That’s not the case. In fact it’s quite the opposite. SDL is forcing 4
bytes alignment on x86_64, which is fine - pointers can be still read,
and hopefully not through __m128.

I’m actually asking for removal of #pragma pack - so that the default
rules take over. Default rules are usually the OS rules, and normally
the compilers for the said platform follow them.

So you would have more followers (compilers) if you don’t enforce these
rules. And these rules were only enforced for MSVC and Borland compilers
(look at my first message)

Thanks!

I’m actually asking for removal of #pragma pack - so that the default rules
take over. Default rules are usually the OS rules, and normally the
compilers for the said platform follow them.

I already explained why this is a bad idea. See that post. If you remove
this, it actually causes a lot of problems when you adjust the default
alignment. It makes things binary incompatible when they don’t need to be.

So you would have more followers (compilers) if you don’t enforce these
rules. And these rules were only enforced for MSVC and Borland compilers
(look at my first message)

GCC understands this, see
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
Sun’s C compiler understands this, see
http://download.oracle.com/docs/cd/E19205-01/821-1383/bkbkl/index.html
IBM’s XL C compiler understands this, see
http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Fcompiler%2Fref%2Fruoptaln.htm
HP’s aCC compiler understands this, see
http://www.physics.irfu.se/aCCdoc/pragmas.htm#pragma-pack>

Thanks!
_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hi Patrick,

I’m fine with the pragma. What I’m not fine is that it’s only enforced
for 3 compilers:

inclue/begin_code.h

/* Force structure packing at 4 byte alignment.
This is necessary if the header is included in code which has structure
packing set to an alternate value, say for loading structures from disk.
The packing is reset to the previous value in close_code.h
*/
#if defined(_MSC_VER) || defined(MWERKS) || defined(BORLANDC)

ifdef _MSC_VER

pragma warning(disable: 4103)

endif

ifdef BORLANDC

pragma nopackwarning

endif

pragma pack(push,4)

#endif /* Compiler needs structure packing set */

It’s only enabled for MSVC, Metrowerks and Borland C (Inprise, whatever).

I don’t see anywhere else this being enabled for GCC, or other "C"
compilers.

I’m stopping this, looks like I’m just creating more confusion.

Thanks!On 8/25/11 8:21 AM, Patrick Baggett wrote:

I'm actually asking for removal of #pragma pack - so that the
default rules take over. Default rules are usually the OS rules, and
normally the compilers for the said platform follow them.

I already explained why this is a bad idea. See that post. If you remove
this, it actually causes a lot of problems when you adjust the default
alignment. It makes things binary incompatible when they don’t need to be.

So you would have more followers (compilers) if you don't enforce
these rules. And these rules were only enforced for MSVC and Borland
compilers (look at my first message)

GCC understands this, see
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
Sun’s C compiler understands this, see
http://download.oracle.com/docs/cd/E19205-01/821-1383/bkbkl/index.html
IBM’s XL C compiler understands this, see
http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Fcompiler%2Fref%2Fruoptaln.htm
HP’s aCC compiler understands this, see
http://www.physics.irfu.se/aCCdoc/pragmas.htm#pragma-pack

Thanks!
_________________________________________________
SDL mailing list
SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
http://lists.libsdl.org/__listinfo.cgi/sdl-libsdl.org
<http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org>

SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hi Patrick,

I’m fine with the pragma. What I’m not fine is that it’s only enforced for
3 compilers:

Then it sounds like it should be extended to GCC (at the least).On Thu, Aug 25, 2011 at 11:19 AM, Dimiter “malkia” Stanev wrote:

It’s only enabled for MSVC, Metrowerks and Borland C (Inprise, whatever).

I don’t see anywhere else this being enabled for GCC, or other "C"
compilers.

Huh, yeah, that’s probably a bug.

–ryan.

That’s not the case. In fact it’s quite the opposite. SDL is forcing 4
bytes alignment on x86_64, which is fine - pointers can be still read,
and hopefully not through __m128.

Hmm…that’s a good point, too…you don’t really want to pack to
32-bits on a 64-bit machine.

Let me think about this a bit more.

–ryan.

Ryan,

__m128 is an aligned type. This ensures that its offset inside of a
structure is also aligned
(linkhttp://msdn.microsoft.com/en-us/library/83ythb65(v=VS.100).aspx,
see “How align Works with Data Packing”), so if you use __m128 in SDL
internally, even with packing it won’t crash (of course the base address has
to be aligned). If you arbitrarily typecast a member that is not of type
__m128 and the expect it to work, you get what you deserve. In addition to
breaking strict aliasing rules, you definitely can’t (safely) arbitrarily
typecast between two types with different alignment requirements and expect
it to work. For example, on SPARC/MIPS/PPC, this is illegal too:

int* x = (int*)someAddress;
*x = 4; //1 in 4 chance this will work

How is that different from:

__m128* x = (__m128*)someAddress;
*__m128 = someValue; //1 in 16 chance this will work (closer to 1/4 in
practice)On Thu, Aug 25, 2011 at 1:20 PM, Ryan C. Gordon wrote:

That’s not the case. In fact it’s quite the opposite. SDL is forcing 4

bytes alignment on x86_64, which is fine - pointers can be still read,
and hopefully not through __m128.

Hmm…that’s a good point, too…you don’t really want to pack to 32-bits
on a 64-bit machine.

Let me think about this a bit more.

–ryan.

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org