    <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  :: Memory Management Patterns in Business-Level Programs</title>
        <link>https://members.accu.org/index.php/articles/2588</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>




<div class="xar-mod-head"><span class="xar-mod-title">Design of applications and programs + Overload Journal #148 - December 2018</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/articles/">All</a>

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

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c67/">Design</a>
<br />

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

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

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

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c393/">o148</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c67-393/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c67+393/">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;Memory Management Patterns in Business-Level Programs</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 05 December 2018 16:31:04 +00:00 or Wed, 05 December 2018 16:31:04 +00:00</p>
<p><strong>Summary:</strong>&nbsp;There are many memory management patterns. Sergey Ignatchenko considers these from an application level.</p>
<p><strong>Body:</strong>&nbsp;<p class="EditorIntro">Disclaimer: as usual, the opinions within this article are those of â€˜No Bugsâ€™ Hare, and do not necessarily coincide with the opinions of the translators and <em>Overload</em> editors; also, please keep in mind that translation difficulties from Lapine (like those described in [<a href="#[Loganberry04]">Loganberry04</a>]) might have prevented an exact translation. In addition, the translator and <em>Overload</em> expressly disclaim all responsibility from any action or inaction resulting from reading this article.</p>

<p>Discussions on â€˜how we should manage memory in our programsâ€™ are ages old; the first discussion which puts together â€˜memory managementâ€™ and â€˜design patternsâ€™ (and which I was able to find) was over 15 years ago, in [<a href="#[Douglass02]">Douglass02</a>] â€“ and BTW is still very relevant.</p>

<h2>On business-level programming</h2>

<p>Still, in spite of the topic being rather ancient, even in [<a href="#[Douglass02]">Douglass02</a>] the discussion is a bit cluttered with details which are not directly relevant for an app-level/business-level programmer (sure, pooling is nice â€“ but 99% of the time it should be an implementation detail hidden from business-level programmer).</p>

<p>In this article, I will try to concentrate on the way memory management is seen by an app-level (more specifically, business-level) developer; this means that I am excluding not only OS kernel programmers, but also developers who are implementing stuff such as lower-level libraries (in other words, if your library is directly calling <code>poll()</code>, this whole thing is not really about you). FWIW, the developers I am trying to represent now are those who are writing business-level logic â€“ more or less similar to the logic which is targeted by programming languages such as C# and Java (while certainly not all Java/C# code qualifies as â€˜business-levelâ€™, most of it certainly does).</p>

<p>A few properties of a typical business-level code:</p>

<ul>
    <li>It changes very often (more often than everything else in sight)</li>
    <li>More often than not, it is â€˜glueâ€™ code</li>
    <li>Development speed is of paramount importance (time to market rulezzz)</li>
    <li>Making changes to existing code quickly (~=â€˜on a whim of some guy in marketing departmentâ€™) is even more important than  â€˜paramountâ€™</li>
    <li>Raw performance of business-level code is usually not that important (it is the way that it calls the pieces of code it glues together which matters for overall performance)</li>
</ul>

<h2>Pattern: Zero Memory Management</h2>

<p>With this in mind, we can start discussing different memory management patterns which are applicable at the business level. As business-level programming has its own stuff to deal with and memory management is rarely a business requirement, more precisely, weâ€™ll be speaking about memory management which we cannot avoid using even at a business level.</p>

<p>It may be difficult to believe, but there are (ok, â€˜wereâ€™) programming languages that didnâ€™t need memory management at all (or, more precisely, with memory management so rudimentary that we can ignore it for our purposes); one example of such a language is FORTRAN77 (though it was expanded with allocatable data in FORTRAN90). Letâ€™s call it Zero Memory Management.</p>

<p>The idea behind Zero Memory Management is simple: as long as we say that all the variables in our program behave â€˜as ifâ€™ theyâ€™re on-stack variables (and any references to them can <em>only </em>go downstream, i.e. from caller to callee), we can easily prove that we donâ€™t need any additional memory management at all, and the program is guaranteed to be correct memory-wise without any additional efforts. In other words:</p>

<p style="margin-left:1em"><em>the best way to avoid problems with pointers is to prohibit them outright.</em></p>

<p>BTW, Zero Memory Management doesnâ€™t prevent us from using heap; the only thing I, as a business-level developer, care about is that all the variables behave â€˜as ifâ€™ theyâ€™re on the stack. It means that things such as <code>std::string</code> and <code>std::unique_ptr&lt;&gt;</code> in C++ (as well as any implementation which uses heap behind the scenes in a similar manner) still qualify as Zero Memory Management (sic!).</p>

<p>In a sense, if we could restrict business-level programming to Zero Memory Management, it would be a Holy Grailâ„¢ from the memory management point of view: there would be no need to think about anything memory-related â€“ our programs would â€˜just workâ€™ memory-wise. Unfortunately, for real-world business programs with complicated data structures, it is not that easy.</p>

<h3>Traversing problem</h3>

<p>One thing which cannot be expressed easily under the Zero Memory Management model is the traversing of complicated data structures. For example, letâ€™s consider the following data structure:</p>

<pre class="programlisting">
  //PSEUDO-CODE
  class OrderItem {
    //some data here
  };
  class Order {
    vector&lt;OrderItem&gt; items;
  };</pre>
  
<p>So far so good, and weâ€™re still well within the Zero Memory Management model, until we need, given an <code>OrderItem</code>, to find the <code>Order</code> to which it belongs.</p>

<p>Traditionally, this task is solved by adding a pointer/reference to <code>Order</code> into <code>OrderItem</code> â€“ but in Zero Memory Management there is no such thing as a pointer, so weâ€™re out of luck. Of course, we can always use a pair of <code>(OrderItem, index-in-vector-of-OrderItems)</code> to express the same thing, but with more complicated data structures with multiple levels of indirections it will quickly (a) become <em>really</em> ugly and (b) start causing significant performance hits.</p>

<p>Letâ€™s call this issue of traversing our complicated data structure a â€˜traversing problemâ€™. In practice, it happens to be bad enough to prevent us from using the otherwise very simple and straightforward Zero Memory Management model &#9785;.</p>

<h2>Pattern: Manual Memory Management</h2>

<p>The second memory management pattern on our list is the dreaded manual memory management. Weâ€™re allocating something on the heap â€“ and obtaining a pointer to it, and then it is our obligation to delete this allocated memory.</p>

<p>Manual memory management has been known at least for 50 years (IIRC, Câ€™s <code>malloc()</code>/<code>free()</code> was not the first such thing); and the problems with it have been known for all those years too. With manual memory management, it is very easy to make one of the following mistakes:</p>

<ul>
    <li>Forget to delete allocated memory (causing memory leak)</li>
    <li>Dereference a pointer to already deleted memory (causing all kinds of trouble, with the worst cases being crashes or data corruption &#9785;).</li>
    <li>On the positive side, we can say that Manual Memory Management <em>does</em> allow us to support arbitrarily-complicated data structures â€“ and very efficiently too. But its lack of protection from silly mistakes is a serious drawback for business-level programming.</li>
</ul>

<h2>Pattern: Reference Counting</h2>

<p><em>NB: I wonâ€™t engage in a discussion whether reference counting should be considered a flavor of Garbage Collection or not. As with any debate about terminology, it is outright silly; what really matters is how the things work, not how we name them.</em></p>

<p>One very simple idea to avoid Manual Memory Management is to use Reference Counting: each object has a reference counter in it, and whenever the object is no longer referenced (because the last reference to an object is dropped) â€“ the object is deleted. Unfortunately, this approach can easily cause loops of objects which are referenced only by each other, causing syntactic memory leaks (also, the semantic memory leaks discussed in the section â€˜Pattern: (full-scale) Garbage Collectionâ€™ below, still apply).</p>

<p>In C++, Reference Counting is represented by <code>std::shared_ptr&lt;&gt;</code>. To help with addressing the loop problem, there is a <code>std::weak_ptr&lt;&gt;</code> which allows us to avoid loops, but it is still the <em>developer</em>â€™s responsibility to make sure loops donâ€™t occur. In addition, there are certain problems with the implementation of <code>std::shared_ptr&lt;&gt;</code> such as the need for the <em>developer</em> to choose the lifetime of the tombstone (very briefly: if weâ€™re using <code>make_shared()</code>, weâ€™re improving locality, but this is at the cost of the memory f<em>or the whole object</em> being kept until the last <code>weak_ptr&lt;&gt;</code> to it is removed, which can take a while &#9785;).</p>

<p>Overall, Reference Counting is not too popular in the industry (and IMNSHO for a good reason too): on the one hand, it doesnâ€™t provide firm safety guarantees, and on the other one â€“ for a vast majority of use cases â€“ it is not really necessary, with <code>std::unique_ptr&lt;&gt;</code> (and its â€˜definite, predictable lifespanâ€™) generally preferred over reference counting most of the time ([<a href="#[Stroustrup]">Stroustrup</a>][<a href="#[Parent13]">Parent13</a>][<a href="#[Weller14]">Weller14</a>], and most importantly &#128521; â€“ my personal experience; IIRC, in my career I have needed an equivalent to <code>shared_ptr&lt;&gt;</code> only thrice â€“ all the cases <em>not</em> at business-level â€“ with number of examples when <code>unique_ptr&lt;&gt;</code> was sufficient, going into goodness knows how many thousands).</p>

<h2>Pattern: (full-scale) Garbage Collection</h2>

<p>After people have tried reference counting (which still failed to achieve the Holy Grailâ„¢ of memory safety), the next thing which arose to deal with memory management was (full-scale) Garbage Collection. The premise of Garbage Collection is simple:</p>

<ul>
    <li>Objects are allocated on the heap (but references can live on the stack).</li>
    <li>An object is not deleted as long as it is reachable from the stack (or from globals) via a chain of references. In other words, <em>as long as there is at least one way to reach the object, it stays alive</em>.</li>
</ul>

<p>Garbage Collection (a) does solve the Traversing Problem, and (b) does avoid the mistakes which are typical with Manual Memory Management. But does this mean that weâ€™ve found a new Holy Grail of Memory Managementâ„¢ with Garbage Collection? Not really.</p>

<p>The Big Fat Problemâ„¢ with Garbage Collection is that if we forget to clean a no-longer-needed reference, it leads to a so-called semantic memory leak, which is a well-known plague of garbage-collected programming languages. Moreover, as has been argued in [<a href="#[NoBugs18]">NoBugs18</a>], for code to be both safe and leak-free, the cleaning of such no-longer-needed references should happen <em>exactly at the same places where weâ€™d call manual </em><code>free()</code><em>/</em><code>delete</code><em> in Manually Managed languages</em>.</p>

<p>More generally, keeping an object alive as long as there is â€˜at least one way to reachâ€™ it (a concept central to garbage collection) means, effectively, loss of control over object lifetimes (they become next-to-impossible to track and control in a sizeable project where anybody can silently store a reference causing all kinds of trouble); this, in turn, creates the potential for Big Fat Memory Leaksâ„¢ â€“ and these have to be avoided in quite a few Big Fat Business-Level Programsâ„¢.</p>

<p>Note that these semantic leaks could be avoided (and control over object life times can be claimed back without introducing the risk of a crash) by using â€˜weak referencesâ€™ for all the references <em>except</em> those references which do express ownership, but such approaches are uncommon for garbage-collected languages (where traditionally â€˜weak referencesâ€™ are seen as a way to implement caches rather than something to prevent unwanted expansion of an objectâ€™s life time, and whatâ€™s more important for practical purposes, â€˜weak referencesâ€™ have <em>much</em> bulkier syntax than default references).</p>


<h2>Pattern: Rust Memory Management (~=â€˜proof engine for dumb pointersâ€™)</h2>

<p>A new kid on the memory management block is the Rust programming language, which has its own approach to ensuring memory safety. Very, very briefly: [within code which is not marked as â€˜unsafeâ€™] Rust tries to <em>prove</em> that your program is memory-safe, and if it cannot prove safety â€“ your program fails to compile.</p>

<p>The problem with such an approach is that the reasoning becomes convoluted, and whatâ€™s <em>much</em> worse is that this proof engine becomes exposed to the developer. Moreover, this restriction is fundamental: Rust cannot (and wonâ€™t be able to, <em>ever</em>) ensure that its proof engine accepts <em>all</em> correct programs (while still rejecting <em>all</em> incorrect ones); in turn, it means that as a Rust programmer, I have to learn not only â€˜how to write correct programsâ€™ (which is inherent for <em>any</em> programming language), but also â€˜how to write programs which the current Rust compiler considers correctâ€™. In practice, this last thing happens to be a Big Pain In The Ahem Neckâ„¢. Personally, Iâ€™d compare the complexity and the amount of jumping through hoops when programming in Rust with the complexity of programming templates in C++ (~=â€˜manageable but really ugly especially for business-level programmingâ€™) â€“ but at least in C++, not all the code is within templates (and <em>using</em> templates in C++ doesnâ€™t suffer from additional complexity).</p>

<p>And as an app-level developer I certainly do NOT want to spend time thinking about Rust proof engine messages that are cryptic for anyone who doesnâ€™t know them. For example, you â€˜cannot borrow <code>foo</code> as immutable because it is also borrowed as mutableâ€™. Furthermore, how I should explain my intentions to the proof engine so it can prove that the program is correct. In Rust, this corresponds to specifying explicit lifetimes.</p>

<p style="margin-left:1em"><em>Sure, it is possible to learn how the Rust proof engine works â€“ but it is yet another Big Fat Thingâ„¢ to remember, and with a cognitive limitation of 7Â±2 entities we can deal with at any given time, it becomes a Big Fat Burdenâ„¢ on us (=â€˜poor defenseless app/business-level programmersâ€™)</em></p>

<p>This complexity IMNSHO stems from an original intention of Rust which Iâ€™d describe as â€˜letâ€™s make an equivalent of the C language and try to prove the correctness of such programsâ€™; and as the C language is all about â€˜dumb pointersâ€™, this means trying to prove the correctness of an arbitrary program with dumb pointers (things donâ€™t change if we rename â€˜pointersâ€™ to â€˜referencesâ€™). And this, as Rust experience IMNSHO demonstrates, is an unsurmountable task &#9785; without placing <em>too much</em> burden on app-level developers (though IMHO Rust still <strong>may</strong> have its use at system level).</p>

 <p>NB: currently, Rust is in the process of improving their proof engine with â€˜Non-Lexical Lifetimesâ€™ (NLL). This is supposed to improve Rustâ€™s ability to prove correctness. IMNSHO, while NLL will indeed allow Rust to prove more cases, it wonâ€™t make the life of the developer significantly simpler. First, there will <em>still</em> be correct programs for which Rust cannot prove correctness, and second, when the Rust compiler fails to prove correctness, understanding <em>why</em> it has failed will become even more cryptic. As one of the NLL features is to analyze conditional control flow <em>across functions</em>, this means that <code>errors become essentially non-local</code>; by changing my function <code>z()</code> in a million-LoC project I can cause a compile-time failure in a function <code>a()</code> which calls <code>b()</code> which calls <code>c()</code> â€¦ which calls <code>y()</code> which calls my function <code>z()</code>. Under these circumstances, figuring out which of the functions <code>a()</code>â€¦<code>z()</code> has to be fixed becomes a hugely non-trivial task (and with a huge potential for fingerpointing between different people/teams about implied contracts between different functions).</p>

<h2>Pattern: Zero+ Memory Management</h2>

<p>And last, but certainly not least, I want to describe a memory management approach which is successfully used in quite a few projects (without this fancy name, of course), ensuring very straightforward programming (and without semantic memory leaks too).</p>

<p>In essence, it is a Zero Memory Management pattern with some kind of {raw|safe|weak} pointers/references added to get around the Traversing Problem. This allows to keep a Zero Memory Management pattern that is very undemanding for the developer, adding only the <code>very minimal</code> fix necessary to address the Traversing Problem.</p>

<p>In essence, this approach relies on expressing data structures via a combination of (a) â€˜owningâ€™ pointers, and (b) â€˜non-owningâ€™ ones. It means that our resulting data structure is a forest, with trees of the forest built from â€˜owningâ€™ pointers, and â€˜non-owningâ€™ pointers going pretty much anywhere within this tree (in particular, in our example above adding a non-owning pointer from <code>OrderItem</code> to <code>Order</code> wonâ€™t be a problem).</p>

<p>Formally, such a forest can express an arbitrary complex data structure. An arbitrary data structure say, in Java, corresponds to a directed graph all parts of which arbitrary data structure are reachable from certain entry points of this directed graph. But then, we can remove those edges which are not necessary for reachability (actually, replacing them with â€˜non-owningâ€™ pointers) and weâ€™ll get a forest which is built out of â€˜owningâ€™ pointers.</p>

<p>Less formally, in all my 20+ years of development, I can remember only three times when I have seen a data structure which doesnâ€™t <em>naturally</em> lend itself to the Zero+ Memory Management model above. Just to illustrate this observation, letâ€™s take a look at the data structures weâ€™re routinely using to express things: structures, nested structures, lists, vectors, hash tables, trees â€“ <em>all</em> of them are <em>naturally</em> expressed via some kind of a tree built from â€˜owning pointersâ€™ (with an occasional â€˜non-owning pointerâ€™ going in the direction opposite to the direction of â€˜owningâ€™ ones). Those few cases when this model wasnâ€™t enough in practice were the same cases when <code>shared_ptr&lt;&gt;</code> was indeed necessary, but <em>all</em> such cases werenâ€™t at the business-level to start with.</p>

<h2>Pattern: Zero+Something Memory Management</h2>

<p>One more thing about Zero+ Memory Management is that we donâ€™t necessarily need to follow this model for <em>all</em> the objects which can arise in our program. Rather, most of the time we can separate our objects into:</p>

<ul>
    <li>long-term objects: for example, those representing the state of our state machine â€“ and</li>
    <li>temporary objects, which are going to be destroyed after we leave our current function.</li>
</ul>

<p>This separation is also consistent with the so-called â€˜generational hypothesisâ€™ which says that young objects are more likely to die than old ones. With this in mind, we can say that Zero+ Memory Management is <em>really</em> important only for long-term objects; for temporary ones we can live with pretty much any other model which works for us. In one example, we may want to use Zero+ for long-term objects, and classical GC-based Memory Management for temporary ones (as long as long-term objects are properly structured, GC will indeed take care of all the temporary ones as soon as temporary objects go out of scope).</p>

<p>Examples of how Zero+Something Memory Management can be used with different programming languages:</p>

<ul>
    <li>C++ with <code>std::unique_ptr&lt;&gt;</code> as â€˜owningâ€™ pointers, and naked C-style pointers for â€˜non-owningâ€™ ones. This is not safe (there is a risk of dangling pointers), but at least will protect against memory leaks. This is actually an approach which was used for quite a few serious C++ projects (including some of my own, including a G20 stock exchange and an MOG with 500K simultaneous players) â€“ and very successfully too.</li>
    
    <li>C++ which uses <code>shared_ptr&lt;&gt;</code> as an implementation of <code>owning_ptr&lt;&gt;</code> (with copying prohibited for <code>owning_ptr&lt;&gt;</code>); this also allows for safe pointers (implemented on top of <code>weak_ptr&lt;&gt;</code>).</li>
    
    <li>â€˜Safe C++â€™ along the lines described in [<a href="#[NoBugs18]">NoBugs18</a>]. Essentially replaces â€˜non-owningâ€™ pointers with their safe counterparts â€“ being able to provide safety guarantees (!). (NB: in [<a href="#[NoBugs18]">NoBugs18</a>] there is also a big chunk of logic aimed to make naked pointers safe for those temporary objects.)</li>
    
    <li>Java with usual Java references as â€˜owningâ€™ pointers, and <code>WeakReference&lt;&gt;</code> as â€˜non-owningâ€™ ones. This will allow us to avoid memory leaks, including most existing semantic memory leaks too (at the very least, it will be much easier to track semantic memory leaks). Zero+Something approach allows us to use the usual Java references for temporary objects (i.e. <em>everywhere</em> except for long-term ones).</li>
    
    <li>C# with usual C# references as â€˜owningâ€™ pointers, and WeakReference (a â€˜shortâ€™ kind(!)) as â€˜non-owningâ€™ ones. Similar to Java, this will allow us to avoid most existing semantic memory leaks. And also same as with Java, Zero+Something approach allows us to use usual C# references for temporary objects (i.e. everywhere except for long-term ones).</li>
</ul>

<h2>Conclusion</h2>

<p>We considered quite a wide range of existing memory management patterns, ranging from Zero Memory Management to Rust Memory Safety. And IMNSHO, at least for business-level programming (which covers <em>most</em> of app-level programming), Zero+Something Memory Management tends to work the best. This approach allows to (a) represent pretty much everything we need, and (b) to avoid pitfalls which are typical for other models. Moreover, it has quite a significant history at least in serious C++ projects (my own ones included), with very good results.</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[Douglass02]"></a>[Douglass02] Bruce Powel Douglass (2002) <em>Real-Time Design Patterns: Robust Scalable Architecture for Real-Time Systems</em>, Addison-Wesley, <a href="https://www.amazon.com/Real-Time-Design-Patterns-Scalable-Architecture/dp/0201699567">https://www.amazon.com/Real-Time-Design-Patterns-Scalable-Architecture/dp/0201699567</a></p>

<p class="bibliomixed"><a id="[Loganberry04]"></a>[Loganberry04] David â€˜Loganberryâ€™, <em>Frithaes! â€“ An Introduction to Colloquial Lapine!</em>, <a href="http://bitsnbobstones.watershipdown.org/lapine/overview.html">http://bitsnbobstones.watershipdown.org/lapine/overview.html</a></p>

<p class="bibliomixed"><a id="[NoBugs18]"></a>[NoBugs18] â€˜No Bugsâ€™ Hare, â€˜Java vs C++: Trading UB for Semantic Memory Leaks (Same Problem, Different Punishment for Failure)â€™, <a href="http://ithare.com/java-vs-c-trading-ub-for-semantic-memory-leaks-same-problem-different-punishment-for-failure">http://ithare.com/java-vs-c-trading-ub-for-semantic-memory-leaks-same-problem-different-punishment-for-failure</a></p>

<p class="bibliomixed"><a id="[Parent13]"></a>[Parent13] Sean Parent (2013) C++ Seasoning, GoingNative, <a href="https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning">https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning</a></p>

<p class="bibliomixed"><a id="[Stroustrup]"></a>[Stroustrup] Bjarne Stroustrup, C++11 FAQ, <a href="http://www.stroustrup.com/C++11FAQ.html#std-shared_ptr">http://www.stroustrup.com/C++11FAQ.html#std-shared_ptr</a></p>

<p class="bibliomixed"><a id="[Weller14]"></a>[Weller14] Jens Weller, shared_ptr addiction, <a href="https://www.meetingcpp.com/blog/items/shared_ptr-addiction.html">https://www.meetingcpp.com/blog/items/shared_ptr-addiction.html</a></p>

<p class="bio"><span class="author"><b>'No Bugs' Hare</b></span> Translated from Lapine by Sergey Ignatchenko using the classic dictionary collated by Richard Adams.</p>

<p class="bio"><span class="author"><b>Sergey Ignatchenko</b></span> Sergey Ignatchenko has 15+ years of industry experience, including being a co-architect of a stock exchange, and the sole architect of a game with 400K simultaneous players. He currently holds the position of Security Researcher.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
