Sunday, November 6, 2011

Smart pointers are dumb

C++ requires one to manage heap memory. Memory management can be tedious and error-prone. If different things reference this memory, and you de-allocate the memory without someone knowing, bad things can happen. If you forget to de-allocate the memory, you have a memory leak.

One solution is to use smart pointers. They let a programmer use similar syntax as normal pointers, with the benefit of memory being automatically cleaned up when nothing references that memory.

What you’ve gained by using smart pointers:

  • Anxiety reduction as you believe you are insulated from having to think about memory management
  • Potentially less typing

What you’ve lost by using smart pointers:

  • Stuff is now happening behind the scenes, but the syntax looks as though nothing is happening behind the scenes. Operators are overloaded. Evil is in the air!
  • The timing of memory de-allocations is implicit. Hidden both in time and in the code.

Normally I’m fine with memory management being done behind the scenes. Our tools are written in C#, a language with a memory manager built in, and I could care less about memory. Tools can be memory hogs to a certain (certainly huge) extent.

However, our runtime game needs to care. I want the easiest, most transparent way to manage memory.

To ease memory management in C++ I do the following:

  • Memory allocations using “new” are only allowed when a chunk (or level) of the game is loaded. Not frame to frame. Likewise, de-allocations are only allowed when a chunk (or level) of the game is unloaded.
  • I use a naming convention for class attributes. An “m” prefix means member, an “mp” prefix means a member that is a pointer, and that the class is responsible for allocating and de-allocating its memory. Finally, I use “mpe” for member pointers for whose memory the class is responsible for neither allocating nor de-allocating. The “e” means external.
  • I use simple macros to ease the typing related to allocation/de-allocation.

So, I centralize (in time) allocations and de-allocations, choose names that immediately identify a class’s responsibility, and wrap some of the clunkiness (such as checking for null before a de-allocation, setting to null after a de-allocation) in macros.

Some people use memory pools to achieve centralizing allocations and preventing a ton of frame-to-frame allocations. If I weren’t the only programmer on this project I would research this. As it stands my solution is easy to implement and transparent, and I can’t waste time researching “best” solutions to a problem that’s under control.


  1. I am so happy for you, Goat. Thanks to this good samaritan you can now educate yourself further on the feeding of goats.


  2. This is interesting stuff to think about. Until recently, I hadn't had any experiences where ownership of objects was something I needed to think about. Recently, however, I created a design for some test code that required instantiation (deep and wide) of more objects that I normally deal with. I had some memory issues when I first ran with it, and it took me several hours to track it all down and make corrections, but I eventually got it all sorted out.

    Anyhow, it's good to know of the existence of smart (dumb) pointers, which I was largely ignorant about until we talked about them yesterday and read your post. I also like your naming convention, which I'll keep in mind if I ever need to employ it.