Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

When it comes to non memory managed languages such as C, C++ or Fortran (my case), it becomes increasingly difficult to keep track of memory allocation/deallocation, especially when ownership must be shared. I implemented refcounting for my objects, but this makes it even more complicated as there's no place where an object gets deallocated. Every reference decrement is a potential deallocation point.

So it's now more and more difficult for me to track down memory leaks. I was wondering about some established techniques to deal with memory management in non-memory managed languages, apart from valgrinding your way around.

Edit: I am more interested in active programming strategies (which are general).

share|improve this question
    
C++'s RAII pattern provides more than enough to adequately deal with this problem. –  DeadMG Aug 6 '12 at 14:24
    
What about C and fortran ? –  Stefano Borini Aug 6 '12 at 14:24
    
It might help if you just forget that passing around ownership exists.... –  tp1 Aug 18 '12 at 9:44

4 Answers 4

You've already covered them.

If shared ownership causes memory management issues, work your design away from shared ownership. Usually this involves designating one part of the code as the owner, and thus responsible for deallocation. Weak pointers (or the equivalent) can help this programmatically. RAII can be more liberally applied when single ownership exists.

If you have refcounting (or another mechanism for auto-deallocation) then you need not care if/where the deallocation occurs. You simply need to test/prove that the structure will correctly deallocate memory when it is supposed to.


A few other things to focus on:

  • Memory management likes patterns. When your code follows consistent patterns, it will have consistent behavior as far as memory management is concerned. When you do detect memory leaks, you can then focus on the exceptional cases, making them easier to find.
  • Shrink your scope. If the objects only live within an isolated scope, it's easier to reason about ownership and their lifetimes.
  • Only allocate what you need. Better than small scopes is no scope. If you don't need to allocate memory (within reason), don't.
share|improve this answer

Tooling is important

There are different tools that may help you. Personally i was using Visual Leak Detector 2 years ago, though it can cause large delays when large blocks are leaked (it displays the contents of the entire leaked block).

If you don't want to recompile (as Visual Leak Detector requires) I would recommend WinDbg, which is both powerful and fast (though it's not as easy to use as one could desire).

Here you are some references on memory leaks and memory management in general:

Coding standards and patterns

Beside tooling, i would advice to work on coding standards and patterns as well as, peer review of the code between developers of the project. This may help to leverage some common approach in trouble shooting memory leak issues.

share|improve this answer
    
I was more interested in active programming strategies (which are general), rather than tools (which are platform dependent). –  Stefano Borini Aug 6 '12 at 13:24

Memory leaks are really a non-issue once you understand how memory management works. To deal with them, you need two things:

First, get a debugging memory manager. I don't know what's available for C, C++ or Fortran, since I'm a Delphi developer, but in Delphi there's a memory manager replacement called FastMM FullDebugMode that will keep track of your allocations and deallocations, and alert you at the end of the program if you've leaked anything. It provides a stack trace, type information, and other useful debug information for each leak, which makes them very simple to track down and fix. You ought to have something similar available for other languages.

Second, you need to understand how to structure memory allocation to prevent leaks from happening. The technique for this can be formally stated as the Single Ownership Principle:

Each variable in your code has one and only one owner, and it’s the responsibility of that owner to free the variable’s memory when it is no longer needed.

What that single owner is will vary depending on what the variables are and what they're used for. Primitives, for example, are owned by the stack and will automatically be cleaned up when a function returns. Most objects, by contrast, are owned by another object. Those that aren't are generally local variables that should be cleaned up by the routine that created them before it exits.

Objects that are shared by multiple other objects do not have multiple owners; if you think of it that way you're asking for trouble. Instead, they should have one single owner, either a reference-counting system or a master object that you know will be around longer than any of the others.

When you internalize the Single Ownership Principle, you'll write a lot less code with leaks. And when you have a debugging memory manager to report on whatever you missed, fixing the few mistakes you do make will stop being a scary prospect.

share|improve this answer
    
I am aware of the single ownership principle, but the problem with it is that it forces knowledge and dependencies at a higher-level object that may not be interested in the entity. The lifetime of the object is a different concern. This is tried and true and the reason behind mem-managed languages, of course. The obvious technique in non-MM langs is to have an allocator that keeps tabs, but again, that forces me to develop an allocator that knows each object type in my code, messy, at least in fortran, where you have a lot of constraint when it comes to messing with memory creatively. –  Stefano Borini Aug 6 '12 at 15:08
    
@Stefano Borini: If I read the answer correctly, Mason is considering something like a C++ std::shared_ptr<> as an owner. This isn't a higher-level object. It would be significantly more complicated in C, and I don't really know what you'd do in Fortran. –  David Thornley Aug 6 '12 at 21:33

I use my own set of wrapper routines for allocation and deallocation, which require each chunk to be identified by a string that identifies the allocation. For example myAlloc(size,"temporary for mumble sort")

In debug mode, every chunk is added to a (potentially large) hashtable, and at exit the remaining leaks are reported along with the strings for the trash. In nondebug mode, only summary bookkeeping is done.

From this scheme, I get a tripwire in production code that warns of unexpected leaks, and I get detailed, immediate feedback when developing about what is leaking.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.