<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Linux Game Publishing Blog &#187; struct packing</title>
	<atom:link href="http://blog.linuxgamepublishing.com/tag/struct-packing/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.linuxgamepublishing.com</link>
	<description>Commercial gaming for Linux</description>
	<lastBuildDate>Sat, 28 Aug 2010 09:06:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The trouble with storing binary data structures</title>
		<link>http://blog.linuxgamepublishing.com/2009/01/29/the-trouble-with-storing-binary-data-structures/</link>
		<comments>http://blog.linuxgamepublishing.com/2009/01/29/the-trouble-with-storing-binary-data-structures/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 08:52:44 +0000</pubDate>
		<dc:creator>Michael Simms (CEO and head of Development)</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[cross platform]]></category>
		<category><![CDATA[data corruption]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[pragma]]></category>
		<category><![CDATA[struct packing]]></category>

		<guid isPermaLink="false">http://blog.linuxgamepublishing.com/?p=20</guid>
		<description><![CDATA[To start off our series of Programming posts, I&#8217;d like to start you off on a technical issue we bumped into yesterday. This isn&#8217;t a new issue for us, but running into it again made us think &#8216;Hey, this would be a great topic for our first technical article&#8217;.
Assumptions: You know some C, You know [...]]]></description>
			<content:encoded><![CDATA[<p>To start off our series of Programming posts, I&#8217;d like to start you off on a technical issue we bumped into yesterday. This isn&#8217;t a new issue for us, but running into it again made us think &#8216;Hey, this would be a great topic for our first technical article&#8217;.</p>
<p>Assumptions: You know some C, You know what a struct in C is.</p>
<p>So, as we were working yesterday on a patch for <a href="http://majesty.linuxgamepublishing.com" target="_self">Majesty</a>, we bumped into an issue</p>
<p>We had the following data structure (this is an abbreviation, the real structure is code we aren&#8217;t really allowed to just post on a website!)</p>
<pre>struct datastruct
{
  char ltr;
  short key;
  int value;
};</pre>
<p>Now, we were using this to read in a blob of binary data from the games datafiles. These data blobs had been stored from Windows when the game was made, and on testing, loaded just fine into Windows.</p>
<p>On Linux, however, reading the data failed.</p>
<pre>struct datastruct datastuff;

//src is a data stream that is the same on Windows and Linux
memcpy(&amp;datastuff,src,sizeof(datastuff));</pre>
<p>The same code on Windows and Linux produces different results! Why can this be?</p>
<p><span style="text-decoration: underline;"><strong>The Answer</strong></span></p>
<p>The answer lies in how the struct is stored.</p>
<p>Windows was being told to &#8216;pack&#8217; its data structures, to save memory. So the data in the structure was held as follows</p>
<pre>Byte     0    1    2    3    4    5    6
Data  |-ltr-||--key--||-----value--------|</pre>
<p>When we were using Linux to read this data back in, it was not packed in the same way. On Linux, the default alignment of a 32 bit machine is to align values on 32 bit boundaries, like so</p>
<pre>Byte     0    1    2    3    4    5    6    7    8    9    10   11
Data   |-ltr-|              |--key--|          |-----value--------|</pre>
<p>As you can see, if you are simply reading in a data stream, you will find that the ltr will be correct, the key will be reading bytes from the middle of the value, and the value could be absolutely anything!</p>
<p>So, how do you fix this?</p>
<p>gcc uses a pragma to resolve this. Use</p>
<p>#pragma pack(n)</p>
<p>on a line of itsown before the struct is defined, where n is the number of bytes you want to pack to. n must be a power of 2 (so 1,2,4,8,16&#8230;).</p>
<p>When you are finished defining things that need to be packed in a certain way restore it using</p>
<pre>#pragma pack()</pre>
<p>So, if you did, at the start of the file defining the structure</p>
<pre>#pragma pack(1)</pre>
<p>Then the datastructure will look the same as in the first example, all scrunched up into 7 bytes. If you use</p>
<pre>#pragma pack(2)</pre>
<p>Then the data structure will be aligned so that each element starts on a 2 byte boundry. This means that it will take up 8 bytes, and there will be a 1 byte gap between ltr and key, which would again cause problems.</p>
<p>The second packing example (the one with all the gaps) is a</p>
<pre>#pragma pack(4)</pre>
<p>example.</p>
<p><span style="text-decoration: underline;"><strong>So, how do you detect this when you find your data is corrupted?</strong></span></p>
<p>It isnt that hard to detect when this has happened. If your data is not the same when you read it in, and you are reading a whole struct in from a binary stream or blob, then chances are, it is a packing issue. Look at the bytes in the stream, try and match them up with the bytes you see in your struct, and see if you can see a pattern, see where bits are missing from the data stream when you look in your struct.</p>
<p>If the data in the struct matches the data in the stream, but the data when you read is different from the data you have saved, don&#8217;t forget that packing works both ways. If you have a struct that is packed using 32 bit (4 byte) boundries, and you write this to a stream, it will look like this</p>
<pre>Byte     0    1    2    3    4    5    6    7    8    9    10   11
Data   |-ltr-|              |--key--|          |-----value--------|</pre>
<p>The bits in the gaps (bytes 1,2,3,6,7) will still be saved, but they can be ANYTHING. Do not rely on them being 0, it isnt always the case.</p>
<p>So if you read this into a packed data structure, you will find that you read in the first byte correctly, you then read the key as 2 completely random bytes, and the value will be made up of bits of the key and random bytes!</p>
<p>We hope that this little tutorial has been helpful to you, and given you a bit of an understanding of this problem. If you spot any mistakes, or see ways to improve it, please drop us a comment on the article!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.linuxgamepublishing.com%2F2009%2F01%2F29%2Fthe-trouble-with-storing-binary-data-structures%2F&amp;linkname=The%20trouble%20with%20storing%20binary%20data%20structures"><img src="http://blog.linuxgamepublishing.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://blog.linuxgamepublishing.com/2009/01/29/the-trouble-with-storing-binary-data-structures/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
