Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Unsmart Pointers, Part I


July, 2005: Unsmart Pointers, Part I

Christopher Diggins is a freelance computer programmer and developer of the Heron programming language. He can be contacted through his web site at http://www.cdiggins.com/.


The discussion of smart pointers seems never-ending, but one thing is quite clear—no smart pointer design is a panacea. Another thing that is relatively apparent is that a pointer class that automatically destroys the resource is not always desirable.

In this article, I describe two hypothetical pointer classes that help prevent and catch errors but do not automatically destroy the resource. I then introduce a single umbrella pointer class, which provides an implementation that covers both cases.

Why Pointer Classes

I want to set things up by revisiting the motivations for pointer classes. Pointer classes are used primarily to:

  • Prevent errors.
  • Catch errors.
  • Simplify resource management.

For the purposes of this article, I am only concerned with the error detection and prevention characteristics of pointer classes. Some of the common programmer errors that pointer classes typically address are:

  • Accessing data that has been freed.
  • Attempting to free data allocated on the stack.
  • Orphaned memory blocks.

Most popular pointer class implementations definitely help with these problems; however, they are not always appropriate. Sometimes automated deletion is not the correct idiom for a specific problem. In other cases, smart pointers may be too complex or inefficient. It would be useful, in many cases, to at least have the error-detection properties of smart pointers, but only during debug builds. But because smart pointers automatically destroy resources, this often isn't feasable. This is where unsmart pointer classes can come in useful.

Undeletable Pointers

A trivial, yet useful, pointer class is one that does not allow explicit or implicit deletion of the resource.This might seem too trivial to be useful, but consider Listing 1. When looking at Listing 1 in isolation, given only the function signature of SomeFunction(), you don't know whether the deletion of p is safe.

Consider, instead, the difference that introducing one little type can make, as in Listing 2. By using an undeletable_ptr type that prevents deletion, you would now have a guarantee of safety due to the simple fact you know that the resource can't have been deleted during the call to SomeFunction().

Another useful case for undeletable pointers is when returning a pointer from a function. There are generally two possibilities for a well-behaved function that returns a pointer:

  • It does not intend for the referenced resource to be deleted.
  • It does intend for the resource to be deleted.

The other possibility, the "may or may not" scenario, is quite rare and is frequently the result of bad practice, so I'll just skip it. Listing 3 shows how an undeletable pointer type can let you use the compiler to catch erroneous usage by preventing casts to raw pointers, thus preventing accidental (or intentional) attempts at deletion.

There are other scenarios where undeletable pointers would arguably be more appropriate than raw pointers—for instance, when taking the address of stack-allocated objects or of member variables

The use of undeletable pointers comes with little cost to the programmer, but carries the significant benefits of making programmer intention more clear and preventing careless accidents.

Deletable Pointers

The complement of the described undeletable pointer is a manually deletable pointer. A deletable pointer provides a Delete() member function and it cannot be assigned or constructed from an undeletable or raw pointer. It is that simple, and like the undeletable pointer, can have virtually no overhead if all calls are inlined properly by the compiler.

The rationale for not allowing assignment from undeletable pointers to deletable pointers should be relatively obvious (you would otherwise be able to delete undeletable pointers through the misuse of casts). However, not supporting assignment from raw pointers gives you a small, yet significant, problem: How do you initialize a deletable pointer from new operations?

My solution is to use another type, new_ptr, to represent the result of new operations. This type is the return type of a new_cast function that converts a raw pointer to a type that can be used; see Listing 4. Unfortunately, this cannot protect you entirely from misuse because new_ptr can also be abused. However, recalcitrant usage is now much easier to detect and avoid than before. It should be clear, even on a Friday afternoon, that there is a problem with the following code:

deletable_ptr<T> x = 
     new_cast(&some_stack_variable); .

No More Raw Pointers

I brought the two hypothetical deletable and undeletable pointer classes together in the single concrete pointer class template ptr. I found it unneccessarily confusing to have two separate implementations of an unsmart pointer class that were so fundamentally similar. This class can be used as a replacement for virtually every case where you might want to use a raw pointer. Listing 5 is my implementation of this class, and Listing 6 shows how you might use it.

The new class ptr has the template parameters: template <typename T, bool deletable_B = false>. This means that ptr is, by default, not deletable, which is the safest of the two options.

And My Point Is...

The simple act of preventing an undeletable pointer from being assigned to a deletable pointer can prevent many potential errors before they occur. Another big, yet subtle, advantage of separating pointers into deletable and undeletable categories is that it forces us to think more coherently about what we intend to do with the pointers and the resources they reference. Remember, preventing errors is much more agile than fixing them after the fact.

This is a two-part article. In the next installment, I'll cover more unsmart pointer classes, such as base_class_ptr, which deals with the problem of missing virtual destructors. I also introduce a reference-counted implementation of ptr, which can detect and prevent even more errors.

Acknowledgments

Thanks to Jonathan Turkanis and Matthew Wilson for their helpful feedback and expert advice.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.