Common Memory Management Problems in C++

Common Memory Management Problems in C++
by Andrei Milea
Avoiding memory leaks
Some strategies can be taken into consideration in order to achieve clean code, free of memory leaks. The best and most common practice is to take care to delete all allocated memory with destructors and use tools like Purify (used in the Google Chrome project) or Valgrind to detect memory leaks and fix them. (For more information on using the Valgrind tool, see Using Valgrind to find memory leaks and invalid memory use.) You should try to be careful to always delete [] memory allocated for arrays and to check for proper deallocation on locally used pointers.

When new is used to gain a block of memory the size reserved by the operating system may be bigger than your request, but never smaller. Because of this and the fact that delete doesn't immediately return the memory to the operating system, when you inspect the whole memory that your program is using you may be made to believe that your application has serious memory leaks. So inspecting the number of bytes the whole program is using should not be used as a way of detecting memory errors. Only if the memory manager indicates a large and continuous growth of memory used should you suspect memory leaks.

A good approach to protect from memory leaks is to use a garbage collector and replace new with its allocator. Even if C++ doesn't provide one (and it will not be present in the new 0X standard either), there are a lot of libraries which can provide good garbage collectors, or you can implement your own. This method is used in some well known applications such as X11, the Mono project, etc.

A half way to garbage collection is to use private heaps, that is, you first allocate a big chunk of memory and manage it in a Heap class (whenever you need new memory to be allocated, a request is being made to the Heap class). Instead of deleting every chunk you allocate for every object, you can delete the whole heap when the objects using it are no longer needed. This can also be used just for backup. In case you forget to delete some object you can be sure that by deleting the Heap there will be no memory leaks remaining.

While the last two approaches are fitted for larger projects and experienced programmers, the C++ standard provides another efficient way of fighting memory leaks, which can be applied by both experienced and intermediate level programmers: smart pointers. They are objects which store pointers to dynamically allocated memory. Writing a smart pointer class is generally not a very hard task, because C++ allows overloading the operator? . One smart pointer provided by the standard library (STL) is called auto_ptr and it is declared in the <memory> header (its class design can be found in Bjarne Stroustrup's book The C++ Programming Language). The following piece of code will illustrate its usage:

void f()
{
        Dialog *dl = new Dialog();
        auto_ptr pdl = dl; 
}

At the end of the function the auto_ptr object will go out of scope and will delete automatically the memory allocated in the first statement. This above technique is used when there are some exceptions thrown between allocating and deallocating memory and you want to make sure there aren't going to be any memory leaks.

For more information on auto_ptr, see Using auto_ptr to Handle Memory.
Debugging dynamic memory
The most common mistake when dealing with memory in general is trying to access a memory location without having proper permission. The bad use of pointers can make possible to access a memory location in the virtual memory that is not actually owned by your application. This will result sometimes in a crash, called a segmentation fault in Unix/Linux based systems and a general protection fault under Windows. Because the virtual memory (presented in the previous part) is divided in pages of fixed size (usually 4096 bytes) the behavior is unpredictable, that is, your application may crash or not, depending on how the memory is mapped for the process. To understand this, this let's assume we have 4 pages of memory allocated by the operating system for our application (the OS can allocate only pages of that fixed size). The policies for every page are kept in the virtual address table along with the mappings between virtual addresses and real locations. So the following code will crash only if the address a[32] falls in a page which is not owned by your application or in one for which you don't have write permission, for example in the text section of the process (see the diagram in the previous part, dynamic memory allocation and virtual memory):

int a = new int[30];
a[32] = 5;

There are some useful applications that can be used to trigger a crash every time you try to access an invalid location in memory, in order to fix them. The most common in the Unix/Linux environment is Electric Fence. In Microsoft Windows application you can make the Visual Studio debugger catch an out of bounds access error by setting it to break when the exception .array out of bounds exceeded. takes place. The tools presented in the previous section, Valgrind and Purify, can also be used to detect memory access errors.

When you don't have a memory error detection tool or don't want to use one, there is always the old-school way: code inspection. To restrict the search in order to speed up the debugging process, you should first review the pieces of code with a dense use of pointers and casts. 

From: www.Cprogramming.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值