    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: new &amp; delete</title>
        <link>https://members.accu.org/index.php/journals/1441</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #4 - Feb 1994 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c233/">04</a>
                    (11)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c233-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c233+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;new &amp; delete</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 February 1994 08:56:00 +00:00 or Tue, 01 February 1994 08:56:00 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<p>There seems to be much ignorance and confusion about the C++ dynamic
memory management tools. As these have been changed and further refined
by the July meeting of XJ16/WG21 (the correct designation of the joint
ANSI and ISO committees standardising C++) I am going to put aside the
other things that I have listed for articles and focus on this.</p>
<p>First of all there are four (not two) operators involved with
associated families of functions. The operators are strictly called:</p>
<pre>new operator<br>new[] operator  (read as new array)<br>delete operator<br>delete[] operator  (delete array)</pre>
<p>The new operator is a built-in action of the language and does two
things. It calls a possibly overloaded operator new function and then
calls a constructor to initialise memory.</p>
<p>The terminology used in technical papers about the memory management
facilities could hardly be worse chosen. From here onwards I will refer
to the new (new[], delete, delete[]) operation when I mean the built-in
memory management facilities. I will refer to the functions that are
(primarily provided by libraries or users) designed to raw memory as
the new (new[] ...) function.&nbsp;&nbsp; In these terms you can
describe the action of the new[] operation as:</p>
<p>Call the appropriate version of the new[] function and then call the
relevant constructor once for each element of the array. (place
information somewhere about the number of elements in the array).</p>
<p>The other two operations are <br>
</p>
<p>delete operation:</p>
<p>Call the destructor for an object of the type pointed to and then
call the appropriate overload of the delete function.</p>
<p>delete[] operation:</p>
<p>Call the destructor for an object of the type pointed to for each
element of the array (find the array size via information squirreled
away by the compiler implementation of the new[] function. Then call
the appropriate version of the delete function.</p>
<p>Please understand that you cannot change the memory management
operations, you can only change the functions that they use. Each
operation directly calls at least two functions (one of them may be
called many times).&nbsp; In the case of the new and new[] operation
failures of the new or new[] function must be dealt with. More about
this later.</p>
<p>Many programmers seem to be unaware that standard implementations of
C++ provide at least two versions of the new function. The first
obtains memory from some heap (in some environments this might not
always be an operating system's heap) and returns a void*. The second
(often called placement new) simply relays a user provided pointer as a
void*. In other words the programmer can provide memory. E.g.</p>
<pre>char * cp;<br>cp=(void *)malloc(20*sizeof(int));<br>int * ip=new (cp) int[20];</pre>
<p>At least a passing knowledge of this form can help you understand
some error messages generated by syntactically incorrect statements
using new. Sometimes the compiler thinks you are trying to write a
placement use when you have simply got in a tangle trying to create a
complex object with new.</p>
<p>Likewise an explicit call of a destructor does not free up the
underlying memory (though it does release resources used by the
destructed object).</p>
<p>As there is no efficient mechanism for the compiler to determine
your intent with regards allocation and de&shy;allocation of resources
it is essential that you make correct use of the memory management
tools of C++. Many programmers have become slack about matching new
with delete and new[] with delete[] (and indeed the rules have been in
a state of flux over the last ten years, which has hardly helped).</p>
<p>Simple objects that do not attach resources to themselves and which
have destructors that do nothing are relatively robust. If you mix the
various memory management tools (including mixing new with free or
malloc with delete) nothing will happen to warn you that you have it
wrong.</p>
<p>As soon as you start writing objects that attach resources (more
memory, files, serial ports etc.) your bad habits will cause problems.
Again you may not notice them as small memory leaks when you have
plenty to spare, failure to close a file and so on will often prove
less than fatal. However the problem is still there and one day it will
matter.</p>
<p>This leads to the first of my rules:</p>
<p>Never use a pointer to handle both single objects created with new
and array objects created with new[]. Doing so is bound to lead to
undetected faults in your product. (If necessary you can always have an
array of one object.)</p>
<h2>A substantive change</h2>
<p>For a committee that constantly rejects proposed changes (such as
attempts to bring the for initialiser statement into line with normal
programmer expectation - but that is another story) XJ16/WG21 had
little hesitation in invalidating all prior usage of new with its
decisions of July '93. Quite apart from splitting off the array
versions as operations in their own right, they also declared that the
normal behaviour for a failure of memory allocation would be to throw
an xalloc exception. This behaviour will replace the previous form that
returns a NULL pointer.</p>
<p>Of course, in the committees defence I must point out that
implementors will elect to provide the previous behaviour as a compiler
option. However it also means that you must carefully document all your
in-house libraries (and vendors will need to document theirs for you)
so that you know which behaviour to expect. If you have never used a
class specific version of new/delete or replaced/overloaded the global
versions this should still concern you. Commercial libraries may have
done so. Worse than this, commercial libraries may be relying on the
now replaced methods.</p>
<p>If you think you have any breathing space to come to terms with this
change I have news for you; the new Borland C++ compiler already
defaults to throwing an xalloc exception.</p>
<p>For many years you are going to have to carefully document the
failure behaviour of new in your programs. You will also need to check
the behaviour in all the third party libraries you use. (There are
other implications to using exceptions, but this is not the place to
explore them.)</p>
<h2>Writing Your Own operator new()</h2>
<p>Let me focus on a simple value class to illustrate the reasons for
both writing your own new function and for the added ability to write
your own new[] function, class Complex will do nicely for this. The
size of instances of this class would normally be small. Programmers
happily return actual Complex values from functions. In all aspects its
expected behaviour is like a built-in.</p>
<p>If you treat it like a built-in and rarely use new to create
instances everything will be fine (and this is the way I would expect
it to be used, but I need a well understood user defined type which is
small and of fixed size) but what happens if you start creating dynamic
instances of Complex?</p>
<p>Very soon you find that your program is spending most of its time
allocating and de-allocating memory. Eventually you might wonder if you
could not do better by taking a block of memory and managing it
directly. As you are looking for speed efficiency you would probably
get a block from the heap and structure it into a linked list of
freespace blocks with each block large enough to hold a single instance
of Complex.</p>
<p>Now the job of your Complex scope new function will be to get the
address of the next free block and return it as a void*.</p>
<p>What happens if there is no free blocks? Perhaps you then get
another large chunk from the OS. Or may be you expect this to be rare
and are willing to revert to the built-in version. If the latter you
are going to need to be much more careful with writing your version of
the delete function for Complex. You can still manage as long as you
keep static information about the address range for your standard
version which can be used by your delete function to discriminate
between normal and abnormal dynamic allocation for Complex.</p>
<p>If you create your own new function for Complex then you must write
your own version of the corresponding delete function. This will have
to return the released block to your free list (or if you are going for
the clever version, it will need to check which version of new
allocated it and either return the released memory to the free list or
to the OS)</p>
<p>The prototypes for straightforward user written version of the new
function and the delete function are:</p>
<pre>void * operator new(size_t size) <br>void * operator delete(void *ptr)</pre>
<p>One problem with this is what happens if you cannot get enough
memory? The first thing is to get the address of the new_handler
function. A typedef is useful here:</p>
<pre>typedef void (*PEH)();</pre>
<p>PEH is a pointer to a function with no parameters returning a void*</p>
<p>then</p>
<pre>PEH&nbsp; currentHandler=set_new_handler(@@@); </pre>
<p>where @@@ represents the address of the next handler after this one
that you want to try - usually NULL. Now if currentHandler is not NULL
you call it and try again.</p>
<p>If it is NULL (i.e. there is no handler) your new function must
either return 0 or throw an xalloc exception.</p>
<p>If you called a handler and it has successfully found some memory,
do not forget to reset the memory handler before returning from your
new function.</p>
<p>The above outline is only the tip of the iceberg as regards writing
your own new and delete functions but it would be an excellent exercise
to try one for yourself. Send your attempts to Mike and we will find
some suitable award for the one which exhibits the best quality code.</p>
<p>At this stage you might ask why the previous rules specified that
arrays of objects (Complex in the case we are looking at) revert to the
use of the global version of the new function?</p>
<p>The reason is that your class based version may not meet the need.
Indeed if you follow the suggested plan for a new function for Complex
it definitely will not work for arrays. Arrays must occupy contiguous
space and apart from memory alignment requirements the programmer is
entitled to expect adjacent members of arrays to be adjacent in memory.
This will not be the case if we use our linked free list - the link
pointers will be taking up space.</p>
<p>Until July '93 you had no mechanism for providing a class based
version of the new function for an array of class objects. This
restriction began to seriously annoy some programmers who wanted to
provide sophisticated memory management on a class by class basis. The
solution was to introduce to extra functions, new[] and delete[] that
would be called by the new[] operation and the delete[] operation.
These now exist in global form and can be replaced, overloaded and
provided within a class scope quite independently of the new and delete
functions.</p>
<p>I am not going to go into detail about these two functions because I
have not had enough time to give them much detailed thought. But the
important point is to remember that they are provided to get raw memory
for an array. They are not responsible for calling
constructors/destructors. That job is out of your hands, it is done
automatically by the new[] operation and delete[] operation.</p>
<p>Hunting around for some way to try to help those with little
experience of memory management functions I came up with the following
concept:</p>
<p>There is something rather like a global virtual function for new
that is called by the C++ new operation. Actually it is more like an
overloaded virtual function. When I use the new operation it will
select the version of the new function appropriate to the set of
parameters that is found in the nearest enclosing scope of the object
being created.</p>
<p>Similar functions exist for the other three operations (new[],
delete and delete[])</p>
<h2>Another Use.</h2>
<p>When I first started programming in Basic (yes I did for a time :-)
I came across various mechanisms used by interpreters to support
strings. One method assigned 4 bytes to each string variable. The first
two were a pointer to the memory where the actual string was and the
second pair gave the length of the string. There was a large heap of
memory that was used as string space and a defined space for the four
byte handles. Periodically the machine would go into a huddle while it
garbage collected its string space. This is quite a complicated process
because the location of the handles must not be changed though the
strings can and will be.</p>
<p>One possible mechanism for garbage collection is to keep a free
store list for your string area and set some trigger mechanism to clean
up storage when a request for string storage fails. The clean-up
routine will be a new_handler specific to the relevant class (I
hesitate to talk about a String class as there is already one of these
per programmer :-)</p>
<p>Now if you are going to do this kind of memory management, your
versions of the new functions will use there own new_handler(s) before
calling that currently returned by a call to set_new_handler(). Why do
I hint that there might be more than one special new_handler()? Well
you would initially look for space to meet the requirement (using which
ever is your chosen algorithm to select from a free list). If this
fails you would call a handler that unified adjacent blocks found in
your free list. Only if this failed would you proceed to garbage
collect your string space.</p>
<p>This mechanism is not specific to storage for strings but can be
used by any class that is constantly re-allocating memory. A good
example of this would be a matrix class. A large enough matrix would
probably be worth allocating via global new but smaller matrices would
be better handled in a reserved block of raw memory for the matrix
class. As matrices vary in size this raw memory would be a good
candidate for garbage collection.</p>
<p>Think carefully about the costs for garbage collection. Its purpose
is to handle limited memory resources efficiently. The result will be a
definite time penalty not only for the garbage collection itself (which
normally eliminates this as an option for real time systems) but for
the extra level of indirection needed to allow relocation of your
object. None-the-less if you are faced with much allocation and
de-allocation of memory for objects of variable size you must either do
the garbage collection yourself, tolerate fragmented memory or hand the
responsibility for garbage collection/fragmented memory to the
operating system.</p>
<p>Of course your application may be an operating system in which case
you are going to have to face up to the problem and learn about the
appropriate data structures and algorithms yourself. Experience of
operating systems to date suggest that there is plenty of scope for
improvement among those programming these.</p>
<p>I already have an ever growing stack of things to write about so I
am going to hand over the task of writing and then writing about a
garbage collection memory management system for class Matrix to you. I
hope that one or more of you will come up with a quality product. Even
if you cannot manage an all singing, all dancing Matrix memory
management system I can assure you that you will learn a lot from
trying to write one. It is not as difficult as it may seem.</p>
<h2>Another Problem</h2>
<p>Arithmetic classes (a subset of value-classes) usually opt to return
instances by value. For example operator + () normally returns a value
not a reference. For classes with small object size this can be lived
with - indeed it is probably efficient for speed and not bad for memory
use. But some of these classes cannot work efficiently if their
arithmetic functions return by value. However any one who has ever
tried to write such a class will be completely familiar with the
problem of trying to return by reference (dangling references are only
one of the problems).</p>
<p>I have a way of fixing this problem so that, for example, the
arithmetic operations for a matrix class can return references without
placing unenforceable syntactic restraints on their use.</p>
<p>Before I tell you my solution I invite you to suggest one of your
own. To make the problem clear I want to fill out the following:</p>
<pre>class Matrix {<br>    // constructor to produce an a by b Matrix <br>    Matrix (int a, int b);<br>    // constructor to create an unitialised <br>    // matrix <br>    Matrix ();<br>    ...<br>    Matrix &amp; operator + (const Matrix &amp;) const; <br>}</pre>
<p>So that</p>
<pre>int main () {<br>    Matrix ml, m2(3,4), m3(3,4), m4(3,4);<br>&nbsp;   ... <br>    //code stuffing some values into m2,m3,m4<br>    ml=m2+m3+m4;<br>    ...<br>}</pre>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
