How to ensure that when writing code in C ++ it does not cause memory leaks?

Running valgrind or cleaning up will be the next steps. But when writing the code itself, how do you guarantee that it will not cause memory leaks? You can provide the following things: - 1: Number of new peers to delete 2: open file handle closed or not

Is there anything else?

+6
c ++ memory-leaks
source share
13 answers

Use the RAII idiom wherever you can

Use smart pointers, for example. std :: auto_ptr where necessary. (do not use auto_prt in any of the standard collections, as it will not work the way you think)

+25
source share

It is not possible to create objects dynamically where possible. Programmers from Java and other similar languages ​​often write things like:

string * s = new string( "hello world" ); 

when they should have written:

 string s = "hello world"; 

Similarly, they create collections of pointers when they need to create collections of values. For example, if you have a class like this:

 class Person { public: Person( const string & name ) : mName( name ) {} ... private: string mName; }; 

Instead of writing code like:

 vector <Person *> vp; 

or even:

 vector <shared_ptr <Person> > vp; 

use the values ​​instead:

 vector <Person> vp; 

You can easily add to this vector:

 vp.push_back( Person( "neil butterworth" ) ); 

and all memory for the Person and the vector is managed for you. Of course, if you need a collection of polymorphic types, you should use (smart) pointers

+14
source share
+7
source share
  • Use RAII
  • Hide copies of copies by default, operator = () in EACH CLASS, if a) your class is trivial and uses only native types, and YOU KNOW THIS WILL ALWAYS BE SO B) you explicitly define your own

The 1) RAII idea is that deletion happens automatically, if you think that “I just called a new one, I will need to remember that you call delete somewhere,” then you are doing something wrong. The deletion must be either a) automatic, or b) placed in the dtor (and which dtor should be obvious).

On 2) Hide the default values. Identification of fraudulent copies of ctors, etc. It can be a nightmare, the easiest way to avoid them is by hiding them. If you have a common “root” object that inherits everything (it can be convenient for debugging / profiling anyway), hide the default values ​​here, and then when something tries to assign / copy the inheriting class, the compiler barfs, because what ctor etc. Not available in base class.

+5
source share

Minimize calls to a new one using STL containers to store your data.

+4
source share

I am with Glen and jalf regarding RAII at every opportunity.

IMHO, you should strive to write completely free code. The only explicit “delete” should be in implementations of the smart pointer class. If you want to write “delete,” go and find the appropriate type of smart pointer. If none of the “industry standards” (upgrade, etc.) fits, and you find that you want to write a new version of bizzare, your architecture may be broken, or at least there will be maintenance problems in the future.

I have long believed that explicit "deletion" is memory management, that "goto" is flow control. More on this in this answer .

+3
source share

I always use std::auto_ptr when I need to create a new object on the heap.

 std::auto_ptr<Foo> CreateFoo() { return std::auto_ptr<Foo>(new Foo()); } 

Even if you call

 CreateFoo() 

he will not miss

+1
source share

The main steps are twofold:

First, keep in mind that for each new deletion is required. So, when you use the new operator, realize what this object will do, how it will be used and how its life will be controlled.

Secondly, make sure you never overwrite the pointer. You can do this using a class of smart pointers instead of raw pointers, but if you really make sure you never use it with an implicit conversion. (example: using the MSXML library, I created the CCOMPtr smart pointer to store the nodes to get the node, you call the get_Node method, passing to the address of the smart pointer that had a conversion operator that returned the pointer-pointer type Unfortunately, this meant that if the smart pointer already stores data, the data of this element will be overwritten, the previous node will leak).

I think these two cases are a time when you can skip memory. If you use only the smart pointer directly - never allowing you to reveal your internal data, you can be safe from the latest problem. If you wrap all your code that uses the new one and delete it in the class (i.e. using RAII), you too can be safe from the first.

Avoiding memory leaks in C ++ is very simple if you follow the above steps.

+1
source share

Two simple rules:

  • Never call delete explicitly (outside the RAII class, that is). Each memory allocation must correspond to the RAII class, which causes deletion in the destructor.
  • Almost never call new explicitly. If you do this, you should immediately wrap the resulting pointer with a smart pointer that will own the distribution and work as described above.

There are two common mistakes in your own RAII classes:

  • Incorrect handling of the copy: who owns the memory rights if the object is copied? Do they create a new distribution? Do you use both copy constructor and assignment operator? Does the last appointment of self-start?
  • Disclaimer of security exceptions. What happens if an exception is thrown during an operation (e.g. assignment)? Does the object return to a consistent state? (he should always do this, no matter what). Does he return to the state that was before the operation? (he should do this when possible) std::vector should handle this, for example, with push_back . This can lead to a resize of the vector, which means 1) the allocation of memory that can be selected, and 2) all existing elements must be copied, each of which can be selected. An algorithm like std::sort should also deal with this. It should call a user-supplied comparator, which can also be thrown! if this happens, will the sequence remain in an acceptable state? Are temporary objects destroyed?

If you handle the above two cases in your RAII classes, it is almost impossible for them to leak memory. And if you use the RAII classes to transfer all resource allocations (memory allocations, files, database connections, and any other type of resource that needs to be acquired and released), your application cannot leak memory.

+1
source share

Make sure that the shared memory created by your application is freed, if no one else uses it, clear the memory mapped files ...

Basically, make sure that you clean up any type of resources created by your application directly or indirectly. File descriptors are just one type of resource that your application can use at runtime.

0
source share

if you produce any tree or graph recursively in your code so that your data structure can eat all of your memory.

0
source share

There are static code analysis tools that do such things; wikipedia is a good place to start your search. Basically, outside of caution and choosing the right containers, you cannot make guarantees about the code you write - therefore, tools like valgrind and gdb are needed.

0
source share

Include the valgrind block and system testing at the beginning of the development cycle and use it sequentially.

0
source share

All Articles