On what platform is func(shared_ptr(...), shared_ptr(...)) really dangerous? - c++

I remember that Scott Meyers taught me that
func(shared_ptr(new P), shared_ptr(new Q));
is dangerous, because (if I remember correctly) the order of memory allocation, reference counting (constructing) and assignment to function parameters allows a leak (theoretically?) to appear in rare circumstances. To prevent this one should encapsulate the shared_ptr in a function call, e.g. in make_shared().
func(make_shared<P>(), make_shared<Q>());
Here is some discussion about it, too.
I would like to know if there are (current) compilers in the field, on certain systems that indeed may leave some hole in some error cases? Or are those times gone, or were they only theoretical, anyway?
Most interesting would be know if any of these have that issue:
g++ 4.x or g++ 2.95, on Linux i386, x64, ARM, m68k or any Windows
Visual C++ on i368, x64 or ARM
Clang/LLVM on Linux, or any of its platforms
How about C++ compilers on/from Sun or IBM, HP-UX?
Has anyone observed this behavior on his specific platform?

This isn't a platform problem, it's an exception-safety issue. So the answer to your actual question is: all those platforms might exhibit the issue.
The memory leak problem arises due to 2 things:
Allocating memory with new might throw bad_alloc
The order in which arguments to functions are evaluated is unspecified.
The docs for boost::shared_ptr capture it nicely here
There is more treatment in detail on the general problem here (GOTW)
The reason it might be "rare" comes about because it's really not that common to get bad_alloc, but your code must handle the possibility safely if it is to avoid memory leaks.
(I say "might" exhibit it - I haven't checked that they all throw bad_alloc if new fails...)

func(shared_ptr(new P), shared_ptr(new Q));
A C++ compiler is free to implement this in the following order:
new Q
new P
construct shared_ptr around allocated P
construct shared_ptr around allocated Q
call func
(A compiler can perform 1, 2, 3, and 4 in any order, as long as 1 is before 4 and 2 before 3).
In the order above, if P's constructor or the call to new throws, Q is a memory leak (memory is allocated but the shared_ptr is not yet constructed around it).
As such, you should call std::make_shared (which handles exceptions on allocation gracefully), and you know that when std::make_shared has returned for one of them, the shared_ptr is fully constructed and will not leak.
I would like to know if there are (current) compilers in the field, on certain systems that indeed may leave some hole in some error cases?
All standards compliant compilers will have this behavior.

because both new operation will be done first, and then they are passed into shared_ptr's constructor, but which shared_ptr constructs first is unspecified, so one of the newly created object may cause a memory leak.

This is unsafe on any platform which has a reordering optimizer, if that optimizer performs the following optimization A;B;A;B => A;A;B;B. This optimization improves code cache efficiency, so in general that's a good idea.
Obviously that optimizer can only rearrange B and A if their relative order is unspecified, which happens to be the case here.

Related

What parts of standard C++ will call malloc/free rather than new/delete?

What parts of standard C++ will call malloc/free rather than new/delete?
This MSDN article lists several cases where malloc/free will be called rather than new/delete:
http://msdn.microsoft.com/en-us/library/6ewkz86d.aspx
I'd like to know if this list is (in increasing order of goodness and decreasing order of likelihood):
True for other common implementations
Exhaustive
Guaranteed by some part of the C++ standard
The context is that I'd like to replace global new/delete and am wondering what allocations I'd miss if I did.
I'd like to know if this list is (in increasing order of goodness and decreasing order of likelihood):
1. True for other common implementations
2. Exhaustive
3. Guaranteed by some part of the C++ standard
I'd say you cannot really tell from that list (I suppose the one given in the Remarks section) what other C++ implementations than MS will use.
The C++ implementation is free to use any of the OS provided system calls arbitrarily. So the answer for all 3 of your questions is: No.
As for use of malloc() vs new() in implementations of the C++ specific part of the compiler ABI:
I think you can suppose that C++ specific implementations will use new() or placement new for any allocator implementations.
If those listed methods use new() (most unlikely) or malloc() internally to allocate memory doesn't matter for a user of the C++ standard library implementations.
NOTE:
If you're asking from the background of planning to override new(), or use placement new to provide your own memory allocation mechanism for all memory allocation in a programs context: That's not the way to go!
You'll have to provide your own versions of malloc(), free() et. al. then. E.g. when using GCC in conjunction with newlib, there are appropriate stubs you can use for this.
A new is basically a wrapped malloc. The compiler is allowed to use stdio functions at will, for example if you try and implement your own memcpy you'll get some weird recursion. If the compiler sees you copying more than a certain amount (say a dumb bit-for-bit copy constructor) it will use memcpy.
So yes, new is sort of a lie, new means "allocate some memory and construct something there and let me write it as one thing", if you allocate an array of floats say, they are uninitialised, malloc will probably be directly used.
Notice I say probably, I'm not sure if they're set to zero these days :P
Anyway, all compiler optimisations ('cept copy elisioning and other return-value-optimisation stuff - BUT THIS IS THE ONLY EXCEPTION) are invisible to you, that is the point. The program cannot tell it was optimised, you'd have to be timing it and stuff. For example:
(x*10)/2
This will not be optimised if the compiler has no idea about the range of x, because x*10 could overflow, but x*5 might not. So if it optimised it'd change the result.
if(x>0 && x<10) {
(x*10)/2
}
will become x*5 because the compiler, being really smart (much more than this) sees "there's no way x*10 can overflow, so x*5 is safe."
If you have a global new/delete that you defined, the compiler cannot optimise because it cannot know it'll have no effects if it does. If you define your own everything it "simplified" to malloc/free will go away.
NOTE:_
I've deliberately ignored the malloc and type-saftey stuff. It's not relevant.
The compiler assumes that malloc, free, memcpy and so forth are all super-optimised and will use them ONLY WHERE SAFE - as described above. There's a GCC thread on the mailing list somewhere where I learned of the memcpy thing.
Calloc and malloc are much, much more low level than new and delete. Firstly malloc and calloc are not safe, because u use cast on type whatever you want, and access of data in that memory is uncontrolled. (You can end up writing on someone else's memory) If you are doing some real low level programming you will have to use malloc and calloc. If you are regular programmer just use new and delete they are much easier. Why do you need precise implementation? (I have to say implementation depends because there are many different ones)

Difference in implementation of malloc and new. Stack implementation?

While allocating memory, the new operator throws an exception if the memory is not available. On the other hand, malloc returns a NULL. What is the reason for the difference in implementation. Also, on static memory allocation, i.e. on the stack, is there an exception if we run out of memory?
I have already gone through the link What is the difference between new/delete and malloc/free?
but did not get my answer on the difference in implementation of the two
The problem with C code is that you are supposed to check the return value of function to make sure they worked correctly. But a lot of code was written that did not check the return value and as a result blew up very nicely when you least expected it.
In the worst case scenario it does not even crash immediately but continues on corrupting memory crashing at some point miles down stream of the error.
Thus in C++ exceptions were born.
Now when there is an error the code does not continue (thus no memory corruption) but unwinds the stack (potentially forcing the application to quit). If you can handle the problem you have to explicitly add code to handle the situation before continuing. Thus you can not accidentally forget to not check the error condition; you either check it or the application will quit.
The use of new fits this design.
If you fail to allocate memory then you must explicitly handle the error.
There is no opportunity to forget to check for the NULL pointer. Thus you can't go and mess up memory by accidentally using a NULL pointer.
Also, on static memory allocation, i.e. on the stack, is there an exception if we run out of memory?
Unfortunately you can not rely on this.
It is implementation defined what happens on stack-overflow. On a lot of systems it is not even possible to detect the situation resulting in memory corruption and probably ultimately a crash.
Note
If you #include <new> then there is a no throw version of new that you can use that returns NULL when there is no memory left. It is best avoided unless have some specialized need.
malloc cannot throw an exception, because that would break compatibility with C. new throws an exception because that is the preferred way in C++ to signal errors.
As far as I know, in early versions of C++, new did indeed return 0 on failure,
One important difference, I suppose, lies in the fact that :
malloc is the C-way of allocating memories ; and there were no exceptions in C
new is the C++, object-oriented and all, way ; and there are exceptions in C++, and using them is more clean.
Why keep malloc in C++ ? I suppose it's because C++ compiler can also work with C code...
... But I've often heard (from teachers, while I was still at school, a couple of years ago) that using malloc in C++ is discouraged, and new should be used instead.
At the risk of perhaps adding some confusion...
malloc is a regular C-function. Because it is C, it can only signal errors by ways that fit into a C program: using the return value, an argument passed by pointer or a global variable (like errno).
new introduces a C++ expression, it calls the operator new to obtain memory and then constructs the object. Either the operator new or the constructors may throw.
Note: there is a no throw version of the new expression
Most operator new are generally implemented in term of malloc, but as I noted there is more to a new expression than simply getting memory, since it's also builds the object(s).
It also takes care of managing up until it releases it to you. That is, if the constructor throws, then it properly disposes of the memory that was allocated, and in case of the new[] expression (which builds an array), calls the destructor of those objects that were already built.
Regarding stack overflows: it depends on your compiler and your operating system. The OS might remark the issue and signals the error, the compiler might check etc...
Note that gcc introduces the split-stack option to compiling, which consists in allocating a minimal stack and then growing it on demand. This neatly sidesteps the issue of possible stack-overflows, but introduces yet another binary compatibility issue since interaction with code that was not built with this option could get hazy; I don't know how they plan on implementing this exactly.
For the sake of completeness, remember also, that you can simulate the old (non throwing) method using nothrow -- this is especially suitable for performance critical parts of your code:
// never throws
char* ptr = new (nothrow) char [1024*1024];
// check pointer for succeeded allocation
if ( !ptr ) {
... // handle error
}

memory management issues in C++

I would like to know what are the common memory management issues associated with C and C++. How can we debug these errors.
Here are few i know
1)uninitialized variable use
2)delete a pointer two times
3)writing array out of bounds
4)failing to deallocate memory
5)race conditions
1) malloc passed back a NULL pointer. You need to cast this pointer to whatever you want.
2) for string, need to allocate an extra byte for the end character.
3) double pointers.
4) (delete and malloc) and (free and new) don't go together
5) see what the actual function returns (return code) on failure and free the memory if it fails.
6) check for size allocating memory malloc(func +1)
7) check how u pass the double pointe **ptr to function
8) check for data size for behaviour undefined function call
9) failure of allocation of memory
Use RAII (Resource Acquisition Is Initialization). You should almost never be using new and delete directly in your code.
Preemptively preventing these errors in the first place:
1) Turn warnings to error levels to overcome the uninitialized errors. Compilers will frequently issue such warnings and by having them accessed as errors you'll be forced to fix the problem.
2) Use Smart pointers. You can find a good versions of such things in Boost.
3) Use vectors or other STL containers. Don't use arrays unless you're using one of the Boost variety.
4) Again, use a container object or smart pointer to handle this issue for you.
5) Use immutable data structures everywhere you can and place locks around modification points for shared mutable objects.
Dealing with legacy applications
1) Same as above.
2) Use integration tests to see how different components of your application play out. This should find many cases of such errors. Seriously consider having a formal peer review done by another group writing a different segment of the application who would come into contact with your naked pointers.
3) You can overload the new operator so that it allocates one extra byte before and after an object. These bytes should then be filled with some easily identifiable value such as 0xDEADBEEF. All you then have to do is check the preceeding byte before and after to witness if and when your memory is being corrupted by such errors.
4) Track your memory usage by running various components of your application many times. If your memory grows, check for missing deallocations.
5) Good luck. Sorry, but this is one of those things that can work 99.9% of the time and then, boom! The customer complains.
In addition to all already said, use valgrind or Bounds Checker to detect all of these errors in your program (except race conditions).
The best technique I know of is to avoid doing pointer operations and dynamic allocation directly. In C++, use reference parameters in preference to pointers. Use stl objects rather than rolling your own lists and containers. Use std::string instead of char *. Failing all that, take Rob K's advice and use RAII wherever you need to do alocations.
For C, there are some simliar things you can try to do, but you are pretty much doomed. Get a copy of Lint and pray for mercy.
Use a good compiler and set warning level to max
Wrap new/malloc and delete/free and bookkeep all allocations/deallocations
Replace raw arrays with an array class that does bounds checking (or use std::vector) (harder to do in C)
See 2.
This is hard, there exists some special debuggers such as jinx that specialize in this but I don't know how good they are.
Make sure you understand when to place object on the heap and when on the stack. As a general rule only put objects on the heap if you must, this will safe you lots of trouble.. Learn STL and use containers provided by the standard lib.
Take a look at my earlier answer to "Any reason to overload global new and delete?" You'll find a number of things here that will help with early detection and diagnosis, as well as a list of helpful tools. Most of the tools and techniques can be applied to either C or C++.
It's worth noting that valgrind's memcheck will spot 4 of your items, and helgrind may help spot the last (data races).
One common pattern I use is the following.
I keep the following three private variables in all allocator classes:
size_t news_;
size_t deletes_;
size_t in_use_;
In the allocator constructor, all of these three are initialized to 0.
Then on,
whenever allocator does a new, it increments news_, and
whenever allocator does a delete, it increments deletes_
Based on that, I put lot of asserts in the allocator code as:
assert( news_ - deletes_ == in_use_ );
This works very good for me.
Addition: I place the assert as precondition and postcondition on all non-trivial methods of the allocator. If the assert blovs, then I know I am doing something wrong. If the assert does not blow, with the all the testing I can do, then I get a reasonably sufficient confidence about the memory management correctness of my program.
1)uninitialized variable use
Automatically detected by compiler (turn warning to full and treat warnings as errors).
2)delete a pointer two times
Don't use RAW pointers. All pointers should by inside either a smart pointer or some form of RAII object that manages the lifetime of the pointer.
3)writing array out of bounds
Don't do it. Thats a logical bug.
You can mitigate it by uisng a container and a method that throws on out of bounds access (vector::at())
4)failing to deallocate memory
Don't use RAW pointers. See (2) above.
5)race conditions
Don't allow them. Allocate resources in priority order to avoid conflicting locks then lock objects when there is a potential for multiple write access (or read access when it is important).
One you forgot:
6) dereferencing pointer after it has been freed.
So far everyone seems to be answering "how to prevent", not "how to debug".
Assuming you're working with code which already has some of these issues, here are some ideas on debugging.
uninitialized variable use
The compiler can detect a lot of this. Initializing RAM to a known value helps in debugging those that escape. In our embedded system, we do a memory test before we leave the bootloader, which leaves all the RAM set to 0x5555. This turns out to be quite useful for debugging: when an integer == 21845, we know it was never initialized.
delete a pointer two times
Visual Studio should detect this at runtime. If you suspect this is happening in other systems, you can debug by replacing the delete call with custom code something like
void delete( void*p){ assert(*(int*)p!=p); _system_delete(p); *(int*)p=p;}
writing array out of bounds
Visual Studio should detect this at runtime. In other systems, add your own sentinels
int headZONE = 0xDEAD;
int array[whatever];
int tailZONE = 0xDEAD;
//add this line to check for overruns
//- place it using binary search to zero in on trouble spot
assert(headZONE==tailZONE&&tailZONE==0xDEAD)
failing to deallocate memory
Watch the stack growth. Record the free heap size before and after points which create and destroy objects; look for unexpected changes. Possibly write your own wrapper around the memory functions to track blocks.
race conditions
aaargh. Make sure you have a logging system with accurate timestamping.

Is it useful to test the return of "new" in C++?

I usually never see test for new in C++ and I was wondering why.
Foo *f = new Foo;
// f is assumed as allocated, why usually, nobody test the return of new?
As per the current standard, new never returns NULL, it throws a std::bad_alloc instead. If you don't want new to throw(as per the old standard) but rather return NULL you should call it by postfixing it with "(std::nothrow)".
i.e.
Foo* foo = new (std::nothrow) Foo;
Of course, if you have a very old or possibly broken toolchain it might not follow the standard.
It all depends on your complier VC++ up to version 6 gives NULL if the new operator fails, on a non MFC application.
Now the problem gets bigger when you use for example STL with VC++ 6, because the STL goes with the standards it will never test for NULL when he needs to get some memory, and guess what will happen under low memory conditions....
So for everybody that still uses VC++ 6 and STL check this article for a Fix.
Don't Let Memory Allocation Failures Crash Your Legacy STL Application
new throws std::bad_alloc by default. If you use default, checking for null is obsolete, but handling exceptions is necessary. This default behavior is consistent with C++ exception safety paradigm - it usually provides that an object is either constructed or not allocated
if you override default by using new (std::nothrow), checking on null is necessary. "New" both allocates and commits pages, so it is possible to run out of memory, either because you ran out of page descriptors, or because there's no physical memory available
research your OS's memory management. C/C++ reference machine does not know how your OS manages memory, so relying on language alone is not safe. For example of memory allocation gone bad, read on C malloc() + Linux overcommit
It all depends which version of C++ the code targets.
The c++ specification for a long time now has stated that, by default at least, failures in new will cause a c++ exception, so any code performing a test would be entirely redundant.
Most programming nowadays also targets virtual memory operating systems where its almost impossible to run out of memory, AND an out-of-memory condition is so fatal anyway that just letting the application crash on the next NULL access is as good a way of any of terminating.
Its only really in embedded programming, where exception handling is deemed to be too much of an overhead, and memory is very limited, that programmers bother to check for new failures.
As quoted here
"In compilers conforming to the ISO C++ standard, if there is not enough memory for the allocation, the code throws an exception of type std::bad_alloc. All subsequent code is aborted until the error is handled in a try-catch block or the program exits abnormally. The program does not need to check the value of the pointer; if no exception was thrown, the allocation succeeded."
Usually no one tests the return of new in new code because Visual Studio now throws the way the standard says.
In old code if a hack has been done to avoid throwing then you'd still better test.

General guidelines to avoid memory leaks in C++ [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What are some general tips to make sure I don't leak memory in C++ programs? How do I figure out who should free memory that has been dynamically allocated?
I thoroughly endorse all the advice about RAII and smart pointers, but I'd also like to add a slightly higher-level tip: the easiest memory to manage is the memory you never allocated. Unlike languages like C# and Java, where pretty much everything is a reference, in C++ you should put objects on the stack whenever you can. As I've see several people (including Dr Stroustrup) point out, the main reason why garbage collection has never been popular in C++ is that well-written C++ doesn't produce much garbage in the first place.
Don't write
Object* x = new Object;
or even
shared_ptr<Object> x(new Object);
when you can just write
Object x;
Use RAII
Forget Garbage Collection (Use RAII instead). Note that even the Garbage Collector can leak, too (if you forget to "null" some references in Java/C#), and that Garbage Collector won't help you to dispose of resources (if you have an object which acquired a handle to a file, the file won't be freed automatically when the object will go out of scope if you don't do it manually in Java, or use the "dispose" pattern in C#).
Forget the "one return per function" rule. This is a good C advice to avoid leaks, but it is outdated in C++ because of its use of exceptions (use RAII instead).
And while the "Sandwich Pattern" is a good C advice, it is outdated in C++ because of its use of exceptions (use RAII instead).
This post seem to be repetitive, but in C++, the most basic pattern to know is RAII.
Learn to use smart pointers, both from boost, TR1 or even the lowly (but often efficient enough) auto_ptr (but you must know its limitations).
RAII is the basis of both exception safety and resource disposal in C++, and no other pattern (sandwich, etc.) will give you both (and most of the time, it will give you none).
See below a comparison of RAII and non RAII code:
void doSandwich()
{
T * p = new T() ;
// do something with p
delete p ; // leak if the p processing throws or return
}
void doRAIIDynamic()
{
std::auto_ptr<T> p(new T()) ; // you can use other smart pointers, too
// do something with p
// WON'T EVER LEAK, even in case of exceptions, returns, breaks, etc.
}
void doRAIIStatic()
{
T p ;
// do something with p
// WON'T EVER LEAK, even in case of exceptions, returns, breaks, etc.
}
About RAII
To summarize (after the comment from Ogre Psalm33), RAII relies on three concepts:
Once the object is constructed, it just works! Do acquire resources in the constructor.
Object destruction is enough! Do free resources in the destructor.
It's all about scopes! Scoped objects (see doRAIIStatic example above) will be constructed at their declaration, and will be destroyed the moment the execution exits the scope, no matter how the exit (return, break, exception, etc.).
This means that in correct C++ code, most objects won't be constructed with new, and will be declared on the stack instead. And for those constructed using new, all will be somehow scoped (e.g. attached to a smart pointer).
As a developer, this is very powerful indeed as you won't need to care about manual resource handling (as done in C, or for some objects in Java which makes intensive use of try/finally for that case)...
Edit (2012-02-12)
"scoped objects ... will be destructed ... no matter the exit" that's not entirely true. there are ways to cheat RAII. any flavour of terminate() will bypass cleanup. exit(EXIT_SUCCESS) is an oxymoron in this regard.
– wilhelmtell
wilhelmtell is quite right about that: There are exceptional ways to cheat RAII, all leading to the process abrupt stop.
Those are exceptional ways because C++ code is not littered with terminate, exit, etc., or in the case with exceptions, we do want an unhandled exception to crash the process and core dump its memory image as is, and not after cleaning.
But we must still know about those cases because, while they rarely happen, they can still happen.
(who calls terminate or exit in casual C++ code?... I remember having to deal with that problem when playing with GLUT: This library is very C-oriented, going as far as actively designing it to make things difficult for C++ developers like not caring about stack allocated data, or having "interesting" decisions about never returning from their main loop... I won't comment about that).
Instead of managing memory manually, try to use smart pointers where applicable.
Take a look at the Boost lib, TR1, and smart pointers.
Also smart pointers are now a part of C++ standard called C++11.
You'll want to look at smart pointers, such as boost's smart pointers.
Instead of
int main()
{
Object* obj = new Object();
//...
delete obj;
}
boost::shared_ptr will automatically delete once the reference count is zero:
int main()
{
boost::shared_ptr<Object> obj(new Object());
//...
// destructor destroys when reference count is zero
}
Note my last note, "when reference count is zero, which is the coolest part. So If you have multiple users of your object, you won't have to keep track of whether the object is still in use. Once nobody refers to your shared pointer, it gets destroyed.
This is not a panacea, however. Though you can access the base pointer, you wouldn't want to pass it to a 3rd party API unless you were confident with what it was doing. Lots of times, your "posting" stuff to some other thread for work to be done AFTER the creating scope is finished. This is common with PostThreadMessage in Win32:
void foo()
{
boost::shared_ptr<Object> obj(new Object());
// Simplified here
PostThreadMessage(...., (LPARAM)ob.get());
// Destructor destroys! pointer sent to PostThreadMessage is invalid! Zohnoes!
}
As always, use your thinking cap with any tool...
Read up on RAII and make sure you understand it.
Bah, you young kids and your new-fangled garbage collectors...
Very strong rules on "ownership" - what object or part of the software has the right to delete the object. Clear comments and wise variable names to make it obvious if a pointer "owns" or is "just look, don't touch". To help decide who owns what, follow as much as possible the "sandwich" pattern within every subroutine or method.
create a thing
use that thing
destroy that thing
Sometimes it's necessary to create and destroy in widely different places; i think hard to avoid that.
In any program requiring complex data structures, i create a strict clear-cut tree of objects containing other objects - using "owner" pointers. This tree models the basic hierarchy of application domain concepts. Example a 3D scene owns objects, lights, textures. At the end of the rendering when the program quits, there's a clear way to destroy everything.
Many other pointers are defined as needed whenever one entity needs access another, to scan over arays or whatever; these are the "just looking". For the 3D scene example - an object uses a texture but does not own; other objects may use that same texture. The destruction of an object does not invoke destruction of any textures.
Yes it's time consuming but that's what i do. I rarely have memory leaks or other problems. But then i work in the limited arena of high-performance scientific, data acquisition and graphics software. I don't often deal transactions like in banking and ecommerce, event-driven GUIs or high networked asynchronous chaos. Maybe the new-fangled ways have an advantage there!
Most memory leaks are the result of not being clear about object ownership and lifetime.
The first thing to do is to allocate on the Stack whenever you can. This deals with most of the cases where you need to allocate a single object for some purpose.
If you do need to 'new' an object then most of the time it will have a single obvious owner for the rest of its lifetime. For this situation I tend to use a bunch of collections templates that are designed for 'owning' objects stored in them by pointer. They are implemented with the STL vector and map containers but have some differences:
These collections can not be copied or assigned to. (once they contain objects.)
Pointers to objects are inserted into them.
When the collection is deleted the destructor is first called on all objects in the collection. (I have another version where it asserts if destructed and not empty.)
Since they store pointers you can also store inherited objects in these containers.
My beaf with STL is that it is so focused on Value objects while in most applications objects are unique entities that do not have meaningful copy semantics required for use in those containers.
Great question!
if you are using c++ and you are developing real-time CPU-and-memory boud application (like games) you need to write your own Memory Manager.
I think the better you can do is merge some interesting works of various authors, I can give you some hint:
Fixed size allocator is heavily discussed, everywhere in the net
Small Object Allocation was introduced by Alexandrescu in 2001 in his perfect book "Modern c++ design"
A great advancement (with source code distributed) can be found in an amazing article in Game Programming Gem 7 (2008) named "High Performance Heap allocator" written by Dimitar Lazarov
A great list of resources can be found in this article
Do not start writing a noob unuseful allocator by yourself... DOCUMENT YOURSELF first.
One technique that has become popular with memory management in C++ is RAII. Basically you use constructors/destructors to handle resource allocation. Of course there are some other obnoxious details in C++ due to exception safety, but the basic idea is pretty simple.
The issue generally comes down to one of ownership. I highly recommend reading the Effective C++ series by Scott Meyers and Modern C++ Design by Andrei Alexandrescu.
There's already a lot about how to not leak, but if you need a tool to help you track leaks take a look at:
BoundsChecker under VS
MMGR C/C++ lib from FluidStudio
http://www.paulnettle.com/pub/FluidStudios/MemoryManagers/Fluid_Studios_Memory_Manager.zip (its overrides the allocation methods and creates a report of the allocations, leaks, etc)
User smart pointers everywhere you can! Whole classes of memory leaks just go away.
Share and know memory ownership rules across your project. Using the COM rules makes for the best consistency ([in] parameters are owned by the caller, callee must copy; [out] params are owned by the caller, callee must make a copy if keeping a reference; etc.)
valgrind is a good tool to check your programs memory leakages at runtime, too.
It is available on most flavors of Linux (including Android) and on Darwin.
If you use to write unit tests for your programs, you should get in the habit of systematicaly running valgrind on tests. It will potentially avoid many memory leaks at an early stage. It is also usually easier to pinpoint them in simple tests that in a full software.
Of course this advice stay valid for any other memory check tool.
Also, don't use manually allocated memory if there's a std library class (e.g. vector). Make sure if you violate that rule that you have a virtual destructor.
If you can't/don't use a smart pointer for something (although that should be a huge red flag), type in your code with:
allocate
if allocation succeeded:
{ //scope)
deallocate()
}
That's obvious, but make sure you type it before you type any code in the scope
A frequent source of these bugs is when you have a method that accepts a reference or pointer to an object but leaves ownership unclear. Style and commenting conventions can make this less likely.
Let the case where the function takes ownership of the object be the special case. In all situations where this happens, be sure to write a comment next to the function in the header file indicating this. You should strive to make sure that in most cases the module or class which allocates an object is also responsible for deallocating it.
Using const can help a lot in some cases. If a function will not modify an object, and does not store a reference to it that persists after it returns, accept a const reference. From reading the caller's code it will be obvious that your function has not accepted ownership of the object. You could have had the same function accept a non-const pointer, and the caller may or may not have assumed that the callee accepted ownership, but with a const reference there's no question.
Do not use non-const references in argument lists. It is very unclear when reading the caller code that the callee may have kept a reference to the parameter.
I disagree with the comments recommending reference counted pointers. This usually works fine, but when you have a bug and it doesn't work, especially if your destructor does something non-trivial, such as in a multithreaded program. Definitely try to adjust your design to not need reference counting if it's not too hard.
Tips in order of Importance:
-Tip#1 Always remember to declare your destructors "virtual".
-Tip#2 Use RAII
-Tip#3 Use boost's smartpointers
-Tip#4 Don't write your own buggy Smartpointers, use boost (on a project I'm on right now I can't use boost, and I've suffered having to debug my own smart pointers, I would definately not take the same route again, but then again right now I can't add boost to our dependencies)
-Tip#5 If its some casual/non-performance critical (as in games with thousands of objects) work look at Thorsten Ottosen's boost pointer container
-Tip#6 Find a leak detection header for your platform of choice such as Visual Leak Detection's "vld" header
If you can, use boost shared_ptr and standard C++ auto_ptr. Those convey ownership semantics.
When you return an auto_ptr, you are telling the caller that you are giving them ownership of the memory.
When you return a shared_ptr, you are telling the caller that you have a reference to it and they take part of the ownership, but it isn't solely their responsibility.
These semantics also apply to parameters. If the caller passes you an auto_ptr, they are giving you ownership.
Others have mentioned ways of avoiding memory leaks in the first place (like smart pointers). But a profiling and memory-analysis tool is often the only way to track down memory problems once you have them.
Valgrind memcheck is an excellent free one.
For MSVC only, add the following to the top of each .cpp file:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
Then, when debugging with VS2003 or greater, you will be told of any leaks when your program exits (it tracks new/delete). It's basic, but it has helped me in the past.
valgrind (only avail for *nix platforms) is a very nice memory checker
If you are going to manage your memory manually, you have two cases:
I created the object (perhaps indirectly, by calling a function that allocates a new object), I use it (or a function I call uses it), then I free it.
Somebody gave me the reference, so I should not free it.
If you need to break any of these rules, please document it.
It is all about pointer ownership.
Try to avoid allocating objects dynamically. As long as classes have appropriate constructors and destructors, use a variable of the class type, not a pointer to it, and you avoid dynamical allocation and deallocation because the compiler will do it for you.
Actually that's also the mechanism used by "smart pointers" and referred to as RAII by some of the other writers ;-) .
When you pass objects to other functions, prefer reference parameters over pointers. This avoids some possible errors.
Declare parameters const, where possible, especially pointers to objects. That way objects can't be freed "accidentially" (except if you cast the const away ;-))).
Minimize the number of places in the program where you do memory allocation and deallocation. E. g. if you do allocate or free the same type several times, write a function for it (or a factory method ;-)).
This way you can create debug output (which addresses are allocated and deallocated, ...) easily, if required.
Use a factory function to allocate objects of several related classes from a single function.
If your classes have a common base class with a virtual destructor, you can free all of them using the same function (or static method).
Check your program with tools like purify (unfortunately many $/€/...).
You can intercept the memory allocation functions and see if there are some memory zones not freed upon program exit (though it is not suitable for all the applications).
It can also be done at compile time by replacing operators new and delete and other memory allocation functions.
For example check in this site [Debugging memory allocation in C++]
Note: There is a trick for delete operator also something like this:
#define DEBUG_DELETE PrepareDelete(__LINE__,__FILE__); delete
#define delete DEBUG_DELETE
You can store in some variables the name of the file and when the overloaded delete operator will know which was the place it was called from. This way you can have the trace of every delete and malloc from your program. At the end of the memory checking sequence you should be able to report what allocated block of memory was not 'deleted' identifying it by filename and line number which is I guess what you want.
You could also try something like BoundsChecker under Visual Studio which is pretty interesting and easy to use.
We wrap all our allocation functions with a layer that appends a brief string at the front and a sentinel flag at the end. So for example you'd have a call to "myalloc( pszSomeString, iSize, iAlignment ); or new( "description", iSize ) MyObject(); which internally allocates the specified size plus enough space for your header and sentinel. Of course, don't forget to comment this out for non-debug builds! It takes a little more memory to do this but the benefits far outweigh the costs.
This has three benefits - first it allows you to easily and quickly track what code is leaking, by doing quick searches for code allocated in certain 'zones' but not cleaned up when those zones should have freed. It can also be useful to detect when a boundary has been overwritten by checking to ensure all sentinels are intact. This has saved us numerous times when trying to find those well-hidden crashes or array missteps. The third benefit is in tracking the use of memory to see who the big players are - a collation of certain descriptions in a MemDump tells you when 'sound' is taking up way more space than you anticipated, for example.
C++ is designed RAII in mind. There is really no better way to manage memory in C++ I think.
But be careful not to allocate very big chunks (like buffer objects) on local scope. It can cause stack overflows and, if there is a flaw in bounds checking while using that chunk, you can overwrite other variables or return addresses, which leads to all kinds security holes.
One of the only examples about allocating and destroying in different places is thread creation (the parameter you pass).
But even in this case is easy.
Here is the function/method creating a thread:
struct myparams {
int x;
std::vector<double> z;
}
std::auto_ptr<myparams> param(new myparams(x, ...));
// Release the ownership in case thread creation is successfull
if (0 == pthread_create(&th, NULL, th_func, param.get()) param.release();
...
Here instead the thread function
extern "C" void* th_func(void* p) {
try {
std::auto_ptr<myparams> param((myparams*)p);
...
} catch(...) {
}
return 0;
}
Pretty easyn isn't it? In case the thread creation fails the resource will be free'd (deleted) by the auto_ptr, otherwise the ownership will be passed to the thread.
What if the thread is so fast that after creation it releases the resource before the
param.release();
gets called in the main function/method? Nothing! Because we will 'tell' the auto_ptr to ignore the deallocation.
Is C++ memory management easy isn't it?
Cheers,
Ema!
Manage memory the same way you manage other resources (handles, files, db connections, sockets...). GC would not help you with them either.
Exactly one return from any function. That way you can do deallocation there and never miss it.
It's too easy to make a mistake otherwise:
new a()
if (Bad()) {delete a; return;}
new b()
if (Bad()) {delete a; delete b; return;}
... // etc.