📄 lib0045.html
字号:
<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Potential Additions</title>
<link rel="STYLESHEET" type="text/css" href="images/xpolecat.css">
<link rel="STYLESHEET" type="text/css" href="images/ie.content.books24x7.css">
</head>
<body >
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<td><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td valign="top" class="v2" align="right"><div STYLE="MARGIN-RIGHT: 0.15in"><a href="LiB0044.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0046.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr>
</table>
<div class="chapter">
<a name="ch05"></a>
<div class="section">
<h2 class="first-section-title"><a name="614"></a><a name="ch05lev1sec5"></a>Potential Additions</h2><p class="first-para">The mark-sweep garbage collector that I provided in this chapter was a bare-bones implementation (and that is an understatement). I deliberately kept things as simple as I could so that you could grasp the big picture without being bogged down with details. Seeing as how my mark-sweep collector had only the minimum set of features, I thought it might be wise to point out a few of the features that could be added to round out the functionality of the mark-sweep collector.</p>
<a name="615"></a><a name="IDX-333"></a>
<div class="section">
<h3 class="sect3-title">
<a name="616"></a><a name="ch05lev2sec9"></a>Object Format Assumptions</h3>
<p class="first-para">So far, I have referred to regions in the heap as "memory blocks." I have done this intentionally so that I could keep the discussion as general as possible. In the end, everything on the heap is merely a block of memory. Depending on what that block of memory represents, however, it may require additional steps when the block of memory is allocated and reclaimed.</p>
<p class="para">For example, objects have both constructors and destructors. When an object is created, its constructor must be called. When an object's storage is reclaimed, its destructor needs to be invoked.</p>
<p class="para">When an object is created off the heap, the compiler will typically pass the object to its constructor. Consider this code:</p>
<div class="informalexample">
<pre class="literallayout">
BluePrint *ptr;
ptr = new BluePrint(15);
</pre>
</div>
<p class="para">In addition to requesting storage from the heap via the new operator, most compilers will also emit the code necessary to pass the new object to its constructor:</p>
<div class="informalexample">
<pre class="literallayout">
; invoke the new operator, allocate 12 bytes
push 12 ; 0000000cH
call ??2@YAPAXI@Z ; operator new
add esp, 4
; pass allocated memory (the object) to the constructor
push 15 ; 0000000fH
mov ecx, DWORD PTR $T196[ebp]
call ??0BluePrint@@QAE@H@Z ; BluePrint::BluePrint
mov DWORD PTR -36+[ebp], eax
</pre>
</div>
<p class="para">If manual memory management is being used, the programmer will include source code that will take care of reclaiming the object's storage in the heap.</p>
<div class="informalexample">
<pre class="literallayout">
delete(ptr);
</pre>
</div>
<p class="para">As before, not only will the compiler emit the instructions necessary to reclaim the object, but it will also emit the instructions necessary to call the object's destructor before reclamation occurs:</p>
<div class="informalexample">
<pre class="literallayout">
push 1
mov ecx, DWORD PTR $T200[ebp]
call ??_GBluePrint@@QAEPAXI@Z ; BluePrint::'scalar
deleting destructor'
mov DWORD PTR -40+[ebp], eax
</pre>
</div>
<p class="para">If a garbage collector is being used to manage reclamation, the programmer will never issue a call to <span class="fixed">delete ()</span>. This means that the garbage collector will have to do this behind the scenes. In order to obey this protocol, a memory manager will need to know which <a name="617"></a><a name="IDX-334"></a>blocks are objects. If a given memory block represents an object, the memory manager will also need to know what type of object it is dealing with.</p>
<p class="para">To institute this type of functionality with my mark-sweep collector, you might want to consider adding another field to the memory block header (see <a class="internaljump" href="#ch05fig11">Figure 5.11</a>).</p>
<div class="figure">
<a name="618"></a><a name="ch05fig11"></a><span class="figuremediaobject"><a href="images/fig362%5F01%5F0%2Ejpg" NAME="IMG_91" target="_parent"><img src="images/fig362_01.jpg" height="211" width="350" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 5.11</span></span>
</div>
<p class="para">This new field, which we'll call <span class="fixed">TYPE</span>, indicates if the memory block is an object, and if it is, then it indexes an element in an array of function pointers. These function pointers store the addresses of destructor functions. This setup is displayed in <a class="internaljump" href="#ch05fig12">Figure 5.12</a>.</p>
<div class="figure">
<a name="619"></a><a name="ch05fig12"></a><span class="figuremediaobject"><a href="images/fig362%5F02%5F0%2Ejpg" NAME="IMG_92" target="_parent"><img src="images/fig362_02.jpg" height="181" width="350" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 5.12</span></span>
</div>
<p class="para">When a memory block is about to be reclaimed, the garbage collector will check to see if the memory block represents an object. If <a name="620"></a><a name="IDX-335"></a>the memory block is an object, the collector will invoke the object's destructor before it reclaims the memory block's storage.</p>
<p class="last-para">Naturally, there are many more details to consider than I've mentioned, such as setting up the table of function pointers and handling nested objects that call different destructors. You will have to experiment with a number of different approaches. Nevertheless, I hope to have guided you in the right direction.</p>
<a></a>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="621"></a><a name="ch05lev2sec10"></a>Variable Heap Size</h3>
<p class="first-para">In all of my implementations, the amount of storage space that the memory manager has to work with is fixed in size. This means that if the manager runs out of memory, it will not be able to service additional requests. To provide greater flexibility, you could allow a memory manager to request more memory from the underlying operating system. This way, when a manager runs out of storage, it simply expands its space by calling the operating system for help.</p>
<p class="para">There are problems related to doing this. For example, if you use an ANSI function, like <span class="fixed">realloc()</span>, to increase the memory manager's storage space, you cannot be sure if the resized memory region will be relocated. Relocation basically invalidates all of an application's existing pointers because the memory regions that they referenced have been moved.</p>
<p class="para">Microsoft's <span class="fixed">HeapReAlloc()</span> Win32 call allows you to specify a special flag value:</p>
<div class="informalexample">
<pre class="literallayout">
newptr = HeapReAlloc( heapHandle,
HEAP_REALLOC_IN_PLACE_ONLY,
oldptr,
1024*1024*10);
</pre>
</div>
<p class="last-para">This requires that the reallocated memory not be moved.</p>
<a></a>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="622"></a><a name="ch05lev2sec11"></a>Indirect Addressing</h3>
<p class="first-para">During the discussion of copying collection and memory reallocation, you have seen how moving memory can make life difficult for an application. The only solution that seems halfway tractable is to traverse the application's stack, heap, and data segment and update the pointer values to reference new locations.</p>
<p class="para">There is, however, a different approach. Rather than have pointers reference actual memory, you can have them store handles. A handle could be implemented simply by a structure that maps an integer handle value to a physical address:</p>
<a name="623"></a><a name="IDX-336"></a>
<div class="informalexample">
<pre class="literallayout">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -