    <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  :: Minimising Stack Use and Other Uses of new</title>
        <link>https://members.accu.org/index.php/journals/1382</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 #3 - Aug 1993 + 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/c225/">03</a>
                    (13)
<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/c225-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c225+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;Minimising Stack Use and Other Uses of new</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 August 1993 11:58:00 +01:00 or Sun, 01 August 1993 11:58:00 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<p>Last issue I promised you an article on the use of new to help
accommodate deeply recursive functions. Before I do so I want to bring
you all up to speed on a technique sometimes called the 'Cheshire Cat'
method. Experienced programmers will already be familiar with it either
by that name or by some other.</p>
<h2>Leaving Only a Smile (pointer)</h2>
<p>This technique was originally developed for two other purposes that
had little to do with minimising stack use; minimise recompilation and
really hide data structures and implementation details from the client
programmer. It has now become popular as a method for providing
implementations for different platforms as transparently as possible.
In the second part of this article I am going to provide an extra twist
that uses one of its side effects, namely that data is dynamically
assigned to the heap.</p>
<p>First let me clear the air for the less experienced reader. Despite
what it says in far too many doorstops that masquerade as books on C++
and OOP, the class is NOT the vehicle to encapsulate an Abstract Data
Type. The C++ class is part of your tool-box for implementing a variety
of programming methods which include a full representation of an ADT.</p>
<p>All programmers that have passed the C++ kindergarten stage know
that it is necessary to use global friends to handle some desirable
operators for many ADTs (for example the insert and extract operators
for I/O). Those who have progressed rather further will know about
handle classes and a variety of other techniques that are desirable to
produce a complete ADT. (There may even be some among you who have read
James Coplien's Advanced Programming Styles and Idioms to the end who
know that classes can be used to support the more traditional, pre-OOP,
block structured methodology).</p>
<p>In simple terms an ADT is represented in C++ by a tightly bound
group of functions and classes with controlled access between them.
This grouping is usually transparent to the client programmer but
should be clearly understood by a library designer or anyone else
seeking to implement an ADT. Unfortunately those who try to stuff too
much into a single client accessible class damage both themselves and
their clients.</p>
<p>Whatever you put into an accessible class must be revealed in its
declaration (i.e. in a header file). This means that client programmers
can inspect your implementation (and with the shocking standard of much
documentation, often need to in order to decide the efficiency of your
implementation in the context of their program. For example, it is not
enough to know that a class can sort data, I need to know what
algorithm has been used to determine its suitability for the profile of
the data I have.)</p>
<p>There are not a few times when you do not want your CPs to inspect
your implementation. Sometimes it contains a currently commercially
secret algorithm, at other times you do not want CPs making assumptions
based on implementation details which may not remain valid in future
releases of your library.</p>
<p>Another circumstance is where you wish to provide alternative
implementations for different platforms or for other commercial reasons
(such as using a relatively poor implementation in a PD or Shareware
version while reserving a much more powerful version for the commercial
release).</p>
<p>Now what about the CP's problems or those of a development team
working on a large project? Every time you change a general header file
all files using that header must be recompiled. Those working on
projects that are only a few thousand lines long may be quite happy to
have an excuse for a tea break. If you were working on a large complex
project you don't want to do a rebuild until you are ready to go home
(I recently heard of a 300 000 line project that took 24 hours for a
complete rebuild).</p>
<p>What we need is complete separation between interface and
implementation. Any competent designer should be able to get the
interface stable early on. Indeed I would expect the interface to be
stable from the end of the prototype stage of program development. What
is not stable for a wide range of reasons is the implementation.</p>
<p>Publicly available header files should only declare the stable
interface. The only files that need access to implementation details
are those that actually provide those details and the specific source
code files that provide the code that puts the interface into effect.</p>
<h2>The Smile (solution)</h2>
<p>Once you have identified the problem the solution is relatively easy
to spot, and even if you do not see it yourself you can easily
appreciate it.</p>
<p>Create two classes. For example:</p>
<pre>class cat {<br>    // the implementation details<br>};<br><br>class cheshire {<br>    cat * smile; <br>public:<br>    // public interface specification <br>};</pre>
<p>All that needs to be made Publicly available via a header file is
the second of these with a declaration of the class name cat.</p>
<p>The source code for cheshire and cat are hived off into their own
file or files. When you change the implementation you recompile the
relevant files and relink (but not recompile) everything else.</p>
<p>You distribute only the public header file together with the
compiled implementation. Now if you change your implementation for
whatever reason your CPs only need to relink with your new object code
files. They have no access and (if you write proper documentation) no
need for access to implementation details. Now you really have hidden
the implementation details which is something that cannot be done with
a single class.</p>
<h2>Cleaning Up</h2>
<p>I believe that where it would be wrong for a class to be
instantiated globally that construction should be controlled. Only
interface classes have any right of access to implementation classes so
I suggest that you should use the following skeleton:</p>
<pre>class cat {<br>    friend class cheshire        // provide restricted access<br>    cat ( ){ .... }              // private constructor<br>    cat (const cat &amp; c) { .... } // and copy constructor<br>    // the rest of the implementation</pre>
<pre>};<br><br>class cheshire {<br>    cat * smile; <br>public:<br>    cheshire (&nbsp;&nbsp;&nbsp; ){ smile = new cat;&nbsp; ... }<br>    ~cheshire (&nbsp;&nbsp;&nbsp; ){&nbsp; ...&nbsp;&nbsp;&nbsp; delete smile;}<br>    // the rest of the interface <br>};</pre>
<p>You will need to do a little work to ensure that items are declared
and defined in the right places. You will also have to be particularly
careful where you put stuff inline as it is quite easy to destroy the
main objectives with careless inlining. You may prefer to eliminate
inline from development code to ensure minimal rebuilds while the
implementation is still fluid. Distribution code may use inline
functions if you are not intending to provide upgrades that only
require relinking or where you are certain that later versions will not
alter the inline function.</p>
<h2>Something More to Smile About (stack saving)</h2>
<p>One of the side-effects of this program technique is that all data
gets transferred from the stack to an allocation from the heap. On many
platforms your stack is a precious resource not to be squandered
lightly. This is even more the case where you are using recursion.</p>
<p>I can remember my first confrontation with this problem. I was
writing a polygon fill function for a graphics package for an
implementation of FORTH. I came across what seemed to be an excellent
algorithm, not least because I could understand exactly how it worked.
However it materialised that it had a fatal flaw, it stacked points to
be filled and called itself recursively.</p>
<p>Even a stack based language such as FORTH could not cope with this
kind of stack explosion.</p>
<p>I hope you can now see why I took this diversion to explain the
'Cheshire Cat'. Clearly the first improvement to any recursive function
is to provide a local data structure to hold the functions internal
data in dynamic memory from a heap. For reasons that will become
apparent I am not going to use a true local class but provide the
necessary functionality via a restricted access global class. <br>
</p>
<pre>class rdata {<br>    friend T recurse ( /* parameter list */ );<br>    rdata ();  // inhibit default constructor<br>    rdata (const rdata &amp; r) {}; // provide restricted copy constructor<br>    rdata ( /* initialiser parameters */){...} // provide constructor for <br>                                               // normal use by recurse()<br>    ~rdata (){ ... } // the data structure <br>};<br><br>T recurse ( /* parameter list */ ){<br>    rdata r=new rdata( /* initialiser parameters */ }<br>    // the rest of the function<br>    delete r; <br>}</pre>
<p>This certainly reduces the amount of stack use in many cases but in
many cases by less than you would like. There is still a parameter list
to consider. If you think that passing parameters by reference will
solve this problem it is time you stopped to consider how reference
passing is probably implemented. Yes, you're right, a hidden pointer,
so each parameter probably costs you storage for a pointer on the
stack. You will also need to consider the return value.</p>
<h2>Smile at Everyone</h2>
<p>One way round this is to include space for the parameters in the
rdata structure. The problem with this is that you have to make rdata
generally accessible so that functions wanting to call the recursive
function can construct an rdata object to pass.</p>
<p>Your code now becomes:</p>
<pre>class rdata {<br>    friend void recurse ( rdata &amp; r);<br>    rdata ();&nbsp;&nbsp;&nbsp;&nbsp; // inhibit default constructor<br>    rdata (const rdata &amp; r) { }; // the data structure <br>public:<br>    rdata ( /* initialiser parameters */){...} // provide constructor for <br>                                               // normal use by recurse()<br>    ~rdata (){ ... } <br>};<br><br>void recurse ( rdata &amp; r){<br>// the rest of the function }</pre>
<p>Why the continued declaration of friendship and the private copy
constructor? Well think about the nature of recurse(). It needs a
mechanism for relaying data to the next call of itself.</p>
<p>The problem with this version is that the responsibility for
constructing (and destructing) an rdata object is passed back to the
calling function which is not something to be encouraged.</p>
<h2>Only Smile at Friends</h2>
<p>A better solution involves using a helper function (which is the
only part that needs to know the details.</p>
<pre>class rdata {<br>    friend T recurse ( /* parameter list */ );<br>    rdata ();&nbsp;&nbsp;&nbsp;&nbsp; // inhibit default constructor<br>    rdata (const rdata &amp; r) { }; // provide restricted copy constructor<br>    rdata ( /* initialiser parameters */ ) { ... }<br>    // provide constructor for normal use by recurse()<br>    ~rdata (){ ... }<br>    void recursif ( ); // the data structure<br>};<br><br>T recurse ( /* parameter&nbsp; list */&nbsp; ){<br>    rdata r=new rdata( /*&nbsp; initialiser parameters */ }<br>    r.recursif();<br>    delete r; <br>}</pre>
<p>Now we are making progress. Its not quite as good as it looks
because we still have at least a return address and a representation of
'this' sitting on the stack for each recursive call.</p>
<p>Too improve this any further we need to try something more drastic.
It is time to get serious and dig out your notes on data structures. If
you are not familiar with writing push down stacks you will have to go
and do some homework because you will need one for the next version.</p>
<h2>Don't Call your Friends, Invite Them to Form a Queue</h2>
<p>Let me concentrate on rdata::recursif(). Note that I have not
specified how the recursion is implemented but have assumed that it is
via the call mechanism but it does not have to be that way.</p>
<p>Have a look at this:</p>
<pre>void recursif(rdata * r) { <br>    int depth =0; <br>    rdata * link= r; <br>    do {<br>        depth++;<br>        link=new rdata(link);<br>        // code up to recursive call<br>    } while ( /* test to end recursion */);<br>    do {<br>        // tail of code executed after return from recursive call<br>        delete link;<br>    } while ( --depth);<br>}</pre>
<p>This would be nice if we could get it to work. To do so we need a
number of things. First we must write a that creates a new copy of the
rdata structure and then pushes it onto the front of a push-down stack
managed through 'link'. We also need to write a destructor that pops
items off the stack. I leave the reader to flesh out the following (try
a simple recursive function till you get the hang of it). <br>
</p>
<pre>class rdata {<br>    friend T recurs( /* parameter list */);<br>    rdata ();&nbsp;&nbsp;&nbsp;&nbsp; // no default construction<br>    rdata (const rdata &amp; r) ; // inhibit<br>    rdata (rdata * ln);&nbsp;&nbsp;&nbsp; // define as required above<br>    rdata ( /* parameter list */) ; // define appropriately<br>    // the actual data structure<br>    rdata * link; // implement stack as linked list <br>}<br><br>T recurs ( /* parameter list */){<br>    rdata * link = new rdata( /* parameter list */); <br>    int depth = 0; <br>    do {<br>        depth++;<br>        link=new rdata(link);<br>        // code up to recursive call<br>    } while ( /* test to end recursion */);<br>    do {<br>        // tail of code executed after return from recursive call<br>        delete link;<br>    } while ( --depth);<br>    T t= ...;&nbsp;&nbsp;&nbsp;&nbsp;  // grab a copy of the return value<br>    delete link;&nbsp;&nbsp; // get rid of initial data set<br>    return t; <br>}</pre>
<p>Notice that we have come the full circle and we are back with a
single function and a class that might be declared as a local class. I
didn't because it was required to be otherwise in intermediate code and
at one time I had the a static pointer to rdata as a member of rdata so
that the copy constructor could be hijacked to push new data sets onto
the push down stack. I decided that solution was unnecessarily fancy.</p>
<p>It is worth looking at the final cost in speed and size compared
with a naive implementation. The link pointer is the only extra piece
of data (apart from any data such as depth that is only used once).
This is balanced by no call overhead on the recursive function. Hence
the total data space will be no more than the naive version and
probably less.</p>
<p>On the speed side there is the overhead for using new. If this gets
too large you can provide your own version of new for the class which
gets memory from the heap in substantial multiples of that for a single
data set. You would then need to overload delete so that this memory
was returned as each block was freed up. Fancier memory management
methods are available to programmers with more experience.</p>
<p>Next time I will look at overloading new and delete and discuss the
revisions introduced in the recent ANSI/ISO meetings to provide
facilities for providing user defined memory management for arrays.</p>
<p>And finally, please provide any feedback that results from your
reading of this article. This is only my first cut at the topic and I
expect that there is plenty of room for improvement.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
