<?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>voyce &#187; address space</title>
	<atom:link href="http://www.voyce.com/index.php/tag/address-space/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.voyce.com</link>
	<description>Programming and debugging tidbits</description>
	<lastBuildDate>Sun, 15 Jan 2012 13:10:46 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Finding the largest free block of address space</title>
		<link>http://www.voyce.com/index.php/2009/08/21/largest-free-block-of-address-space/</link>
		<comments>http://www.voyce.com/index.php/2009/08/21/largest-free-block-of-address-space/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 20:57:12 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[WinDbg]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[address space]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[perfmon]]></category>
		<category><![CDATA[private bytes]]></category>
		<category><![CDATA[win32]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=258</guid>
		<description><![CDATA[I&#8217;ve been seeing problems recently with fragmented virtual address space. During the lifetime of a process, bits and pieces of memory are allocated throughout the 2GB 32-bit address space to such an extent that large contiguous blocks of free space are no longer available. If anything subsequently requires a large block of memory (like, for [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://72.47.193.211/wp-content/uploads/2009/08/buildings_small.png"><img src="http://72.47.193.211/wp-content/uploads/2009/08/buildings_small.png" alt="Buildings" title="Buildings" width="100" height="100" class="alignleft size-full wp-image-268" /></a>I&#8217;ve been seeing problems recently with fragmented virtual address space. During the lifetime of a process, bits and pieces of memory are allocated throughout the 2GB 32-bit address space to such an extent that large contiguous blocks of free space are no longer available. If anything subsequently requires a large block of memory (like, for instance, a somewhat out-of-date version of the GHC runtime), it will fail to get it.</p>
<p>It&#8217;s obvious looking at the output from <a href="http://www.voyce.com/index.php/2009/07/28/diagnosing-out-of-memory-errors-with-vmmap/">VMmap</a> or windbg&#8217;s <code>!address</code> command what the largest contiguous block is, e.g.</p>
<pre>
0:008> !address -summary
....
Largest free region: Base 07300000 - Size 63ed0000 (1637184 KB)
</pre>
<p>But what if you need that number in order to make a decision at run-time? For instance, to decide whether your process is in a fit state to continue, or if it should instead commit <a href="http://en.wikipedia.org/wiki/Seppuku">hara-kiri</a>. In that case, you need to access the information programmatically. That&#8217;s where the immensely useful <a href="http://msdn.microsoft.com/en-us/library/aa366907(VS.85).aspx">VirtualQueryEx</a> function comes in&#8230;<br />
<span id="more-258"></span><br />
VirtualQueryEx gives you information on a single page of your virtual address space at a time. Pages size are dependent on the architecture and OS, but if you just want to iterate over all of them, you don&#8217;t need to add any special handling; the function returns the size of the page in an element of the <a href="http://msdn.microsoft.com/en-us/library/aa366775(VS.85).aspx">MEMORY_BASIC_INFORMATION</a> structure, so you can simply move to the &#8216;next&#8217; page regardless of size.</p>
<p>If you&#8217;re interested in free space, you&#8217;ll need to find all the pages that have a state of MEM_FREE (0&#215;10000), and that&#8217;s pretty much all there is to it. By keeping track of how much space falls into a continuous range of MEM_FREE pages you can get to the number reported by VMmap and <code>!address</code>.</p>
<p>Here&#8217;s some C++ code that returns the address of the largest free contiguous block in <code>largestFreestart</code and the size in <code>largestFree</code>. Enjoy!</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">	MEMORY_BASIC_INFORMATION mbi<span style="color: #008080;">;</span>
	DWORD start <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">bool</span> recording <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
	DWORD freestart <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span>, largestFreestart <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
	__int64 <span style="color: #0000dd;">free</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span>, largestFree <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		SIZE_T s <span style="color: #000080;">=</span> VirtualQueryEx<span style="color: #008000;">&#40;</span>hproc, <span style="color: #0000ff;">reinterpret_cast</span><span style="color: #000080;">&lt;</span>lpvoid<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>start<span style="color: #008000;">&#41;</span>, <span style="color: #000040;">&amp;</span>mbi, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>mbi<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>s <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>mbi<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>GetLastError<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> ERROR_INVALID_PARAMETER<span style="color: #008000;">&#41;</span>
				<span style="color: #0000ff;">return</span> ReportError<span style="color: #008000;">&#40;</span>GetLastError<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, _T<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Failed to VirtualQueryEx at %08x&quot;</span><span style="color: #008000;">&#41;</span>, start<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000ff;">else</span>
				<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>mbi.<span style="color: #007788;">State</span> <span style="color: #000080;">==</span> MEM_FREE<span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>recording<span style="color: #008000;">&#41;</span>
				freestart <span style="color: #000080;">=</span> start<span style="color: #008080;">;</span>
			<span style="color: #0000dd;">free</span> <span style="color: #000040;">+</span><span style="color: #000080;">=</span> mbi.<span style="color: #007788;">RegionSize</span><span style="color: #008080;">;</span>
			recording <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">else</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>recording<span style="color: #008000;">&#41;</span>
			<span style="color: #008000;">&#123;</span>
				<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">free</span> <span style="color: #000080;">&gt;</span> largestFree<span style="color: #008000;">&#41;</span>
				<span style="color: #008000;">&#123;</span>
					largestFree <span style="color: #000080;">=</span> <span style="color: #0000dd;">free</span><span style="color: #008080;">;</span>
					largestFreestart <span style="color: #000080;">=</span> freestart<span style="color: #008080;">;</span>
				<span style="color: #008000;">&#125;</span>
			<span style="color: #008000;">&#125;</span>
			<span style="color: #0000dd;">free</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
			recording <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		start <span style="color: #000040;">+</span><span style="color: #000080;">=</span> mbi.<span style="color: #007788;">RegionSize</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2009/08/21/largest-free-block-of-address-space/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Diagnosing out of memory errors with VMMap &#8211; Part 2</title>
		<link>http://www.voyce.com/index.php/2009/07/29/diagnosing-out-of-memory-errors-with-vmmap-part-2/</link>
		<comments>http://www.voyce.com/index.php/2009/07/29/diagnosing-out-of-memory-errors-with-vmmap-part-2/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 08:32:34 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[address space]]></category>
		<category><![CDATA[heap]]></category>
		<category><![CDATA[perfmon]]></category>
		<category><![CDATA[private bytes]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=743</guid>
		<description><![CDATA[(I had problems with WordPress choking on this long post, so I&#8217;ve split it into 2 parts. The first part is here. This is the second part).

Private data
This is the data that is explicitly allocated by the process, or blocks of memory that contain the allocated data. So when you&#8217;re allocating from the heap, for [...]]]></description>
			<content:encoded><![CDATA[<p>(I had problems with WordPress choking on this long post, so I&#8217;ve split it into 2 parts. The first part is <a href="http://www.voyce.com/index.php/2009/07/28/diagnosing-out-of-memory-errors-with-vmmap/">here</a>. This is the second part).<br />
<span id="more-743"></span></p>
<h3>Private data</h3>
<p>This is the data that is explicitly allocated by the process, or blocks of memory that contain the allocated data. So when you&#8217;re allocating from the heap, for instance, using code like:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1024</span><span style="color: #000040;">*</span><span style="color: #0000dd;">1024</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span></pre></div></div>

<p>you can see how the heap manager manages address space; creating reserved segments of a fixed size, then committing parts of them as required.<br />
When a segment is full, it will create a new one of double the size.</p>
<p>Allocate first 256*1024 bytes:<br />
<div id="attachment_220" class="wp-caption alignleft" style="width: 303px"><a href="http://72.47.193.211/wp-content/uploads/2009/07/heap1.png"><img src="http://72.47.193.211/wp-content/uploads/2009/07/heap1.png" alt="After allocating first 256KB" title="heap1" width="293" height="41" class="size-full wp-image-220" /></a><p class="wp-caption-text">After allocating first 256KB</p></div><br />
<br clear="all"/>Allocate another 256*1024 bytes:<br />
<div id="attachment_221" class="wp-caption alignleft" style="width: 303px"><a href="http://72.47.193.211/wp-content/uploads/2009/07/heap2.png"><img src="http://72.47.193.211/wp-content/uploads/2009/07/heap2.png" alt="After allocating another 256KB" title="heap2" width="293" height="41" class="size-full wp-image-221" /></a><p class="wp-caption-text">After allocating another 256KB</p></div><br />
<br clear="all"/>Allocate yet another 256*1024 bytes:<br />
<div id="attachment_222" class="wp-caption alignleft" style="width: 303px"><a href="http://72.47.193.211/wp-content/uploads/2009/07/heap3.png"><img src="http://72.47.193.211/wp-content/uploads/2009/07/heap3.png" alt="And another..." title="heap3" width="293" height="41" class="size-full wp-image-222" /></a><p class="wp-caption-text">And another...</p></div><br />
<br clear="all"/>Allocate another 256*1024 bytes. This time a new heap segment is created:<br />
<div id="attachment_223" class="wp-caption alignleft" style="width: 299px"><a href="http://72.47.193.211/wp-content/uploads/2009/07/heap4.png"><img src="http://72.47.193.211/wp-content/uploads/2009/07/heap4.png" alt="And yet another..." title="heap4" width="289" height="84" class="size-full wp-image-223" /></a><p class="wp-caption-text">And yet another...</p></div><br clear="all"/>Many heaps in the process, all attempting to create segments in this way can cause problems, see Heap contention.</p>
<h2>Causes of out of memory errors</h2>
<h3>Fragmentation</h3>
<p>If you&#8217;re experiencing out of memory errors, the first thing to check is the largest free block size. Obviously if you&#8217;re requesting more than the available size, your allocation will fail. Remember that large requests may be made implicitly by mechanisms that are outside your control. For instance, Windows heaps expand geometrically, attempting to grab a segment of double the previous size each time, e.g. 16, 32, 64, 128MB. As you can see, allocating a single byte when the 64MB segment is full will result in the heap manager trying to reserve a 128MB block.</p>
<p>So once you&#8217;ve seen that the largest free block is small, the question then is: why? It&#8217;s either due to genuine memory exhaustion or address space fragmentation.</p>
<h3>Heap contention</h3>
<p>Fragmentation can be due to multiple heaps contending for contiguous address space. This is typically the case when you have a mix of VC++ code that is built using different versions of the runtime libraries (msvcrt.dll, msvcr70.dll, msvcr80.dll, msvcr90.dll), each of which manages it&#8217;s own heap.</p>
<p>Remember that heap segments need to be reserved as a contiguous block of address space, but if your virtual memory is fragmented, the heap manager may not be able to obtain one. In this case, it will fall-back to creating segments of smaller sizes. The problem is that there&#8217;s a limit to the number of segments that can be created &#8211; a measly 32 in Windows XP &#8211; so if fragmentation causes it to create more, smaller segments this limit may be reached. If a new segment cannot be created you&#8217;ll get out of memory errors.</p>
<p>If you suspect this, you can use <code>!heap -m</code> to see details of the segment count and sizes for each heap. To identity the heap associated with each version of the MSVC runtime, ensure you&#8217;ve got the appropriate symbols loaded and then use <code>dd msvcr80!_crtheap L1</code> to see the address.</p>
<h3>Address space exhaustion</h3>
<p>It may also be possible that you <i>really have</i> exhausted your 2GB address space. This can happen when your process wastes lots of address space due to allocation granularity. For example calling <code>VirtualAlloc</code> without an address will cause the OS to choose one for you, and as the documentation states, this will be rounded to a multiple of the allocation granularity, 64KB. So if you happen to allocate lots of objects of only a few bytes with direct calls to VirtualAlloc, you will waste almost 64KB a time. Although this might not seem significant in a 2GB address space, it all adds up.</p>
<p>One of the symptoms of address space exhaustion is DLLs failing to load. I noticed recently that a COM <code>CoCreateInstance</code> call was failing because the only address space left to load the DLL into was way up into the area usually reserved for OS DLLs such as ntdll.dll.</p>
<h3>Other tips</h3>
<p>By default the allocations are ordered by Address (the first column) and, because things are generally allocated in increasingly higher locations in memory, this can serve as a useful &#8220;timeline&#8221; of the app&#8217;s allocations. It&#8217;s not guaranteed though: DLLs that have an explicit load address don&#8217;t follow this pattern (for example, VBE6.DLL always loads at 0&#215;65000000). You can use it to see roughly when threads and heaps are created and files are mapped though.</p>
<h3>Summary</h3>
<p>So, I hope you find this information useful in interpreting the output from VMMap. It&#8217;s a very good way of getting visibility on the state of your processes and it&#8217;s certainly more intuitive than having to use the !address and !heap commands in WinDbg.</p>
<p>Good hunting!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2009/07/29/diagnosing-out-of-memory-errors-with-vmmap-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

