Related
I understand the benefits of using new against malloc in C++. But for specific cases such as primitive data types (non array) - int, float etc., is it faster to use malloc than new?
Although, it is always advisable to use new even for primitives, if we are allocating an array so that we can use delete[].
But for non-array allocation, I think there wouldn't be any constructor call for int? Since, new operator allocates memory, checks if it's allocated and then calls the constructor. But just for primitives non-array heap allocation, is it better to use malloc than new?
Please advise.
Never use malloc in C++. Never use new unless you are implementing a low-level memory management primitive.
The recommendation is:
Ask yourself: "do I need dynamic memory allocation?". A lot of times you might not need it - prefer values to pointers and try to use the stack.
If you do need dynamic memory allocation, ask yourself "who will own the allocated memory/object?".
If you only need a single owner (which is very likely), you should
use std::unique_ptr. It is a zero cost abstraction over
new/delete. (A different deallocator can be specified.)
If you need shared ownership, you should use std::shared_ptr. This is not a zero cost abstraction, as it uses atomic operations and an extra "control block" to keep track of all the owners.
If you are dealing with arrays in particular, the Standard Library provides two powerful and safe abstractions that do not require any manual memory management:
std::array<T, N>: a fixed array of N elements of type T.
std::vector<T>: a resizable array of elements of type T.
std::array and std::vector should cover 99% of your "array needs".
One more important thing: the Standard Library provides the std::make_unique and std::make_shared which should always be used to create smart pointer instances. There are a few good reasons:
Shorter - no need to repeat the T (e.g. std::unique_ptr<T>{new T}), no need to use new.
More exception safe. They prevent a potential memory leak caused by the lack of a well-defined order of evaluation in function calls. E.g.
f(std::shared_ptr<int>(new int(42)), g())
Could be evaluated in this order:
new int(42)
g()
...
If g() throws, the int is leaked.
More efficient (in terms of run-time speed). This only applies to std::make_shared - using it instead of std::shared_ptr directly allows the implementation to perform a single allocation both for the object and for the control block.
You can find more information in this question.
It can still be necessary to use malloc and free in C++ when you are interacting with APIs specified using plain C, because it is not guaranteed to be safe to use free to deallocate memory allocated with operator new (which is ultimately what all of the managed memory classes use), nor to use operator delete to deallocate memory allocated with malloc.
A typical example is POSIX getline (not to be confused with std::getline): it takes a pointer to a char * variable; that variable must point to a block of memory allocated with malloc (or it can be NULL, in which case getline will call malloc for you); when you are done calling getline you are expected to call free on that variable.
Similarly, if you are writing a library, it can make sense to use C++ internally but define an extern "C" API for your external callers, because that gives you better binary interface stability and cross-language interoperability. And if you return heap-allocated POD objects to your callers, you might want to let them deallocate those objects with free; they can't necessarily use delete, and making them call YourLibraryFree when there are no destructor-type operations needed is unergonomic.
It can also still be necessary to use malloc when implementing resizable container objects, because there is no equivalent of realloc for operator new.
But as the other answers say, when you don't have this kind of interface constraint tying your hands, use one of the managed memory classes instead.
It's always better to use new. If you use malloc you still have to check manually if space is allocated.
In modern c++ you can use smart pointers. With make_unique and make_shared you never call new explicitly. std::unique_ptr is not bigger than the underlying pointer and the overhead of using it is minimal.
The answer to "should I use new or malloc" is single responsibillity rule.
Resource management should be done by a type that has that as its sole purpose.
Those classes already exists, such as unique_ptr, vector etc.
Directly using either malloc or new is a cardinal sin.
zwol's answer already gives the correct correctness answer: Use malloc()/free() when interacting with C interfaces only.
I'm not going to repeat those details, I'm going to answer the performance question.
The truth is, that the performance of malloc() and new can, and does differ. When you perform an allocation with new, the memory will generally be allocated via call to the global operator new() function, which is distinct from malloc(). It is trivial to implement operator new() by calling through to malloc(), but this is not necessarily done.
As a matter of fact, I've seen a system where an operator new() that calls through to malloc() would outperform the standard implementation of operator new() by roughly 100 CPU cycles per call. That's definitely a measurable difference, and a clear indication that the standard implementation does something very different from malloc().
So, if you are worried about performance, there is three things to do:
Measure your performance.
Write replacement implementations for the global operator new() function and its friends.
Measure your performance and compare.
The gains/losses may or may not be significant.
What is the use of malloc and free when we have new and delete in C++. I guess function of both free and delete is same.
They're not the same. new calls the constructor, malloc just allocates the memory.
Also, it's undefined behavior mixing the two (i.e. using new with free and malloc with delete).
In C++, you're supposed to use new and delete, malloc and free are there for compatibility reasons with C.
In C++, it is rarely useful that one would use malloc & free instead of new& delete.
One Scenario I can think of is:
If you do not want to get your memory initialized by implicit constructor calls, and just need an assured memory allocation for placement new then it is perfectly fine to use malloc and free instead of new and delete.
On the other hand, it is important to know that mallocand new are not same!
Two important differences straight up are:
new guarantees callng of constructors of your class for initializing the class members while mallocdoes not, One would have to do an additional memset or related function calls post an malloc to initialize the allocated memory to do something meaningful.
A big advantage is that for new you do not need to check for NULL after every allocation, just enclosing exception handlers will do the job saving you redundant error checking unlike malloc.
First, when you speak of new and delete, I assume you mean the
expressions, and not the operator new and operator delete functions.
The new and delete expressions are not related to malloc and
free, and only manage memory incidentally; their main role is to
manage object lifetime: a new expression will call the operator new
function to obtain memory, and then call the constructor; a delete
expression will call the destructor before calling operator delete to
free the memory. For the most part, objects should be created, and
not simply allocated, which means using the expressions exclusively.
There are some rare cases where one wants to separate allocation and
initialization (creation); implementing things like std::vector is a
classical example, where you'll allocate for many objects in one go, but
only construct one at a time. In such cases, you'll use the operator
new function for allocation, and placement new for initialization; at
the other end, you'll explicitly call the constructor (something like
p->~T()) for destruction, and use the operator delete function to
free the memory.
Off hand, I can only think of two cases where you'd use malloc and
free in C++. The first is to implement your own replacements of the
::operator new and ::operator delete functions. (I often replace
the global ::operator new and ::operator delete with debugging
versions, which trace allocations, put guard zones around the allocated
memory, etc.) The other is when interacting with a legacy library
written in C: if the library says to pass a pointer to memory allocated
by malloc (because it will free it itself using free), or more
commonly, returns a pointer to memory allocated by malloc, which
you're expected to free, then you must use malloc and free. (The
better libraries will provide their own allocation and deallocation
functions, which do more or less what the new and delete operators
do, but there will always be things like strdup().)
I stumbled upon Stack Overflow question Memory leak with std::string when using std::list<std::string>, and one of the comments says this:
Stop using new so much. I can't see any reason you used new anywhere you did. You can create objects by value in C++ and it's one of the huge advantages to using the language. You do not have to allocate everything on the heap. Stop thinking like a Java programmer.
I'm not really sure what he means by that.
Why should objects be created by value in C++ as often as possible, and what difference does it make internally? Did I misinterpret the answer?
There are two widely-used memory allocation techniques: automatic allocation and dynamic allocation. Commonly, there is a corresponding region of memory for each: the stack and the heap.
Stack
The stack always allocates memory in a sequential fashion. It can do so because it requires you to release the memory in the reverse order (First-In, Last-Out: FILO). This is the memory allocation technique for local variables in many programming languages. It is very, very fast because it requires minimal bookkeeping and the next address to allocate is implicit.
In C++, this is called automatic storage because the storage is claimed automatically at the end of scope. As soon as execution of current code block (delimited using {}) is completed, memory for all variables in that block is automatically collected. This is also the moment where destructors are invoked to clean up resources.
Heap
The heap allows for a more flexible memory allocation mode. Bookkeeping is more complex and allocation is slower. Because there is no implicit release point, you must release the memory manually, using delete or delete[] (free in C). However, the absence of an implicit release point is the key to the heap's flexibility.
Reasons to use dynamic allocation
Even if using the heap is slower and potentially leads to memory leaks or memory fragmentation, there are perfectly good use cases for dynamic allocation, as it's less limited.
Two key reasons to use dynamic allocation:
You don't know how much memory you need at compile time. For instance, when reading a text file into a string, you usually don't know what size the file has, so you can't decide how much memory to allocate until you run the program.
You want to allocate memory which will persist after leaving the current block. For instance, you may want to write a function string readfile(string path) that returns the contents of a file. In this case, even if the stack could hold the entire file contents, you could not return from a function and keep the allocated memory block.
Why dynamic allocation is often unnecessary
In C++ there's a neat construct called a destructor. This mechanism allows you to manage resources by aligning the lifetime of the resource with the lifetime of a variable. This technique is called RAII and is the distinguishing point of C++. It "wraps" resources into objects. std::string is a perfect example. This snippet:
int main ( int argc, char* argv[] )
{
std::string program(argv[0]);
}
actually allocates a variable amount of memory. The std::string object allocates memory using the heap and releases it in its destructor. In this case, you did not need to manually manage any resources and still got the benefits of dynamic memory allocation.
In particular, it implies that in this snippet:
int main ( int argc, char* argv[] )
{
std::string * program = new std::string(argv[0]); // Bad!
delete program;
}
there is unneeded dynamic memory allocation. The program requires more typing (!) and introduces the risk of forgetting to deallocate the memory. It does this with no apparent benefit.
Why you should use automatic storage as often as possible
Basically, the last paragraph sums it up. Using automatic storage as often as possible makes your programs:
faster to type;
faster when run;
less prone to memory/resource leaks.
Bonus points
In the referenced question, there are additional concerns. In particular, the following class:
class Line {
public:
Line();
~Line();
std::string* mString;
};
Line::Line() {
mString = new std::string("foo_bar");
}
Line::~Line() {
delete mString;
}
Is actually a lot more risky to use than the following one:
class Line {
public:
Line();
std::string mString;
};
Line::Line() {
mString = "foo_bar";
// note: there is a cleaner way to write this.
}
The reason is that std::string properly defines a copy constructor. Consider the following program:
int main ()
{
Line l1;
Line l2 = l1;
}
Using the original version, this program will likely crash, as it uses delete on the same string twice. Using the modified version, each Line instance will own its own string instance, each with its own memory and both will be released at the end of the program.
Other notes
Extensive use of RAII is considered a best practice in C++ because of all the reasons above. However, there is an additional benefit which is not immediately obvious. Basically, it's better than the sum of its parts. The whole mechanism composes. It scales.
If you use the Line class as a building block:
class Table
{
Line borders[4];
};
Then
int main ()
{
Table table;
}
allocates four std::string instances, four Line instances, one Table instance and all the string's contents and everything is freed automagically.
Because the stack is faster and leak-proof
In C++, it takes but a single instruction to allocate space—on the stack—for every local scope object in a given function, and it's impossible to leak any of that memory. That comment intended (or should have intended) to say something like "use the stack and not the heap".
The reason why is complicated.
First, C++ is not garbage collected. Therefore, for every new, there must be a corresponding delete. If you fail to put this delete in, then you have a memory leak. Now, for a simple case like this:
std::string *someString = new std::string(...);
//Do stuff
delete someString;
This is simple. But what happens if "Do stuff" throws an exception? Oops: memory leak. What happens if "Do stuff" issues return early? Oops: memory leak.
And this is for the simplest case. If you happen to return that string to someone, now they have to delete it. And if they pass it as an argument, does the person receiving it need to delete it? When should they delete it?
Or, you can just do this:
std::string someString(...);
//Do stuff
No delete. The object was created on the "stack", and it will be destroyed once it goes out of scope. You can even return the object, thus transfering its contents to the calling function. You can pass the object to functions (typically as a reference or const-reference: void SomeFunc(std::string &iCanModifyThis, const std::string &iCantModifyThis). And so forth.
All without new and delete. There's no question of who owns the memory or who's responsible for deleting it. If you do:
std::string someString(...);
std::string otherString;
otherString = someString;
It is understood that otherString has a copy of the data of someString. It isn't a pointer; it is a separate object. They may happen to have the same contents, but you can change one without affecting the other:
someString += "More text.";
if(otherString == someString) { /*Will never get here */ }
See the idea?
Objects created by new must be eventually deleted lest they leak. The destructor won't be called, memory won't be freed, the whole bit. Since C++ has no garbage collection, it's a problem.
Objects created by value (i. e. on stack) automatically die when they go out of scope. The destructor call is inserted by the compiler, and the memory is auto-freed upon function return.
Smart pointers like unique_ptr, shared_ptr solve the dangling reference problem, but they require coding discipline and have other potential issues (copyability, reference loops, etc.).
Also, in heavily multithreaded scenarios, new is a point of contention between threads; there can be a performance impact for overusing new. Stack object creation is by definition thread-local, since each thread has its own stack.
The downside of value objects is that they die once the host function returns - you cannot pass a reference to those back to the caller, only by copying, returning or moving by value.
C++ doesn't employ any memory manager by its own. Other languages like C# and Java have a garbage collector to handle the memory
C++ implementations typically use operating system routines to allocate the memory and too much new/delete could fragment the available memory
With any application, if the memory is frequently being used it's advisable to preallocate it and release when not required.
Improper memory management could lead memory leaks and it's really hard to track. So using stack objects within the scope of function is a proven technique
The downside of using stack objects are, it creates multiple copies of objects on returning, passing to functions, etc. However, smart compilers are well aware of these situations and they've been optimized well for performance
It's really tedious in C++ if the memory being allocated and released in two different places. The responsibility for release is always a question and mostly we rely on some commonly accessible pointers, stack objects (maximum possible) and techniques like auto_ptr (RAII objects)
The best thing is that, you've control over the memory and the worst thing is that you will not have any control over the memory if we employ an improper memory management for the application. The crashes caused due to memory corruptions are the nastiest and hard to trace.
I see that a few important reasons for doing as few new's as possible are missed:
Operator new has a non-deterministic execution time
Calling new may or may not cause the OS to allocate a new physical page to your process. This can be quite slow if you do it often. Or it may already have a suitable memory location ready; we don't know. If your program needs to have consistent and predictable execution time (like in a real-time system or game/physics simulation), you need to avoid new in your time-critical loops.
Operator new is an implicit thread synchronization
Yes, you heard me. Your OS needs to make sure your page tables are consistent and as such calling new will cause your thread to acquire an implicit mutex lock. If you are consistently calling new from many threads you are actually serialising your threads (I've done this with 32 CPUs, each hitting on new to get a few hundred bytes each, ouch! That was a royal p.i.t.a. to debug.)
The rest, such as slow, fragmentation, error prone, etc., have already been mentioned by other answers.
Pre-C++17:
Because it is prone to subtle leaks even if you wrap the result in a smart pointer.
Consider a "careful" user who remembers to wrap objects in smart pointers:
foo(shared_ptr<T1>(new T1()), shared_ptr<T2>(new T2()));
This code is dangerous because there is no guarantee that either shared_ptr is constructed before either T1 or T2. Hence, if one of new T1() or new T2() fails after the other succeeds, then the first object will be leaked because no shared_ptr exists to destroy and deallocate it.
Solution: use make_shared.
Post-C++17:
This is no longer a problem: C++17 imposes a constraint on the order of these operations, in this case ensuring that each call to new() must be immediately followed by the construction of the corresponding smart pointer, with no other operation in between. This implies that, by the time the second new() is called, it is guaranteed that the first object has already been wrapped in its smart pointer, thus preventing any leaks in case an exception is thrown.
A more detailed explanation of the new evaluation order introduced by C++17 was provided by Barry in another answer.
Thanks to #Remy Lebeau for pointing out that this is still a problem under C++17 (although less so): the shared_ptr constructor can fail to allocate its control block and throw, in which case the pointer passed to it is not deleted.
Solution: use make_shared.
To a great extent, that's someone elevating their own weaknesses to a general rule. There's nothing wrong per se with creating objects using the new operator. What there is some argument for is that you have to do so with some discipline: if you create an object you need to make sure it's going to be destroyed.
The easiest way of doing that is to create the object in automatic storage, so C++ knows to destroy it when it goes out of scope:
{
File foo = File("foo.dat");
// Do things
}
Now, observe that when you fall off that block after the end-brace, foo is out of scope. C++ will call its destructor automatically for you. Unlike Java, you don't need to wait for the garbage collection to find it.
Had you written
{
File * foo = new File("foo.dat");
you would want to match it explicitly with
delete foo;
}
or even better, allocate your File * as a "smart pointer". If you aren't careful about that it can lead to leaks.
The answer itself makes the mistaken assumption that if you don't use new you don't allocate on the heap; in fact, in C++ you don't know that. At most, you know that a small amount of memory, say one pointer, is certainly allocated on the stack. However, consider if the implementation of File is something like:
class File {
private:
FileImpl * fd;
public:
File(String fn){ fd = new FileImpl(fn);}
Then FileImpl will still be allocated on the stack.
And yes, you'd better be sure to have
~File(){ delete fd ; }
in the class as well; without it, you'll leak memory from the heap even if you didn't apparently allocate on the heap at all.
new() shouldn't be used as little as possible. It should be used as carefully as possible. And it should be used as often as necessary as dictated by pragmatism.
Allocation of objects on the stack, relying on their implicit destruction, is a simple model. If the required scope of an object fits that model then there's no need to use new(), with the associated delete() and checking of NULL pointers.
In the case where you have lots of short-lived objects allocation on the stack should reduce the problems of heap fragmentation.
However, if the lifetime of your object needs to extend beyond the current scope then new() is the right answer. Just make sure that you pay attention to when and how you call delete() and the possibilities of NULL pointers, using deleted objects and all of the other gotchas that come with the use of pointers.
When you use new, objects are allocated to the heap. It is generally used when you anticipate expansion. When you declare an object such as,
Class var;
it is placed on the stack.
You will always have to call destroy on the object that you placed on the heap with new. This opens the potential for memory leaks. Objects placed on the stack are not prone to memory leaking!
One notable reason to avoid overusing the heap is for performance -- specifically involving the performance of the default memory management mechanism used by C++. While allocation can be quite quick in the trivial case, doing a lot of new and delete on objects of non-uniform size without strict order leads not only to memory fragmentation, but it also complicates the allocation algorithm and can absolutely destroy performance in certain cases.
That's the problem that memory pools where created to solve, allowing to to mitigate the inherent disadvantages of traditional heap implementations, while still allowing you to use the heap as necessary.
Better still, though, to avoid the problem altogether. If you can put it on the stack, then do so.
I tend to disagree with the idea of using new "too much". Though the original poster's use of new with system classes is a bit ridiculous. (int *i; i = new int[9999];? really? int i[9999]; is much clearer.) I think that is what was getting the commenter's goat.
When you're working with system objects, it's very rare that you'd need more than one reference to the exact same object. As long as the value is the same, that's all that matters. And system objects don't typically take up much space in memory. (one byte per character, in a string). And if they do, the libraries should be designed to take that memory management into account (if they're written well). In these cases, (all but one or two of the news in his code), new is practically pointless and only serves to introduce confusions and potential for bugs.
When you're working with your own classes/objects, however (e.g. the original poster's Line class), then you have to begin thinking about the issues like memory footprint, persistence of data, etc. yourself. At this point, allowing multiple references to the same value is invaluable - it allows for constructs like linked lists, dictionaries, and graphs, where multiple variables need to not only have the same value, but reference the exact same object in memory. However, the Line class doesn't have any of those requirements. So the original poster's code actually has absolutely no needs for new.
I think the poster meant to say You do not have to allocate everything on the heap rather than the the stack.
Basically, objects are allocated on the stack (if the object size allows, of course) because of the cheap cost of stack-allocation, rather than heap-based allocation which involves quite some work by the allocator, and adds verbosity because then you have to manage data allocated on the heap.
Two reasons:
It's unnecessary in this case. You're making your code needlessly more complicated.
It allocates space on the heap, and it means that you have to remember to delete it later, or it will cause a memory leak.
Many answers have gone into various performance considerations. I want to address the comment which puzzled OP:
Stop thinking like a Java programmer.
Indeed, in Java, as explained in the answer to this question,
You use the new keyword when an object is being explicitly created for the first time.
but in C++, objects of type T are created like so: T{} (or T{ctor_argument1,ctor_arg2} for a constructor with arguments). That's why usually you just have no reason to want to use new.
So, why is it ever used at all? Well, for two reasons:
You need to create many values the number of which is not known at compile time.
Due to limitations of the C++ implementation on common machines - to prevent a stack overflow by allocating too much space creating values the regular way.
Now, beyond what the comment you quoted implied, you should note that even those two cases above are covered well enough without you having to "resort" to using new yourself:
You can use container types from the standard libraries which can hold a runtime-variable number of elements (like std::vector).
You can use smart pointers, which give you a pointer similar to new, but ensure that memory gets released where the "pointer" goes out of scope.
and for this reason, it is an official item in the C++ community Coding Guidelines to avoid explicit new and delete: Guideline R.11.
The core reason is that objects on heap are always difficult to use and manage than simple values. Writing code that are easy to read and maintain is always the first priority of any serious programmer.
Another scenario is the library we are using provides value semantics and make dynamic allocation unnecessary. Std::string is a good example.
For object oriented code however, using a pointer - which means use new to create it beforehand - is a must. In order to simplify the complexity of resource management, we have dozens of tools to make it as simple as possible, such as smart pointers. The object based paradigm or generic paradigm assumes value semantics and requires less or no new, just as the posters elsewhere stated.
Traditional design patterns, especially those mentioned in GoF book, use new a lot, as they are typical OO code.
new is the new goto.
Recall why goto is so reviled: while it is a powerful, low-level tool for flow control, people often used it in unnecessarily complicated ways that made code difficult to follow. Furthermore, the most useful and easiest to read patterns were encoded in structured programming statements (e.g. for or while); the ultimate effect is that the code where goto is the appropriate way to is rather rare, if you are tempted to write goto, you're probably doing things badly (unless you really know what you're doing).
new is similar — it is often used to make things unnecessarily complicated and harder to read, and the most useful usage patterns can be encoded have been encoded into various classes. Furthermore, if you need to use any new usage patterns for which there aren't already standard classes, you can write your own classes that encode them!
I would even argue that new is worse than goto, due to the need to pair new and delete statements.
Like goto, if you ever think you need to use new, you are probably doing things badly — especially if you are doing so outside of the implementation of a class whose purpose in life is to encapsulate whatever dynamic allocations you need to do.
One more point to all the above correct answers, it depends on what sort of programming you are doing. Kernel developing in Windows for example -> The stack is severely limited and you might not be able to take page faults like in user mode.
In such environments, new, or C-like API calls are prefered and even required.
Of course, this is merely an exception to the rule.
new allocates objects on the heap. Otherwise, objects are allocated on the stack. Look up the difference between the two.
While learning different languages, I've often seen objects allocated on the fly, most often in Java and C#, like this:
functionCall(new className(initializers));
I understand that this is perfectly legal in memory-managed languages, but can this technique be used in C++ without causing a memory leak?
Your code is valid (assuming functionCall() actually guarantees that the pointer gets deleted), but it's fragile and will make alarm bells go off in the heads of most C++ programmers.
There are multiple problems with your code:
First and foremost, who owns the pointer? Who is responsible for freeing it? The calling code can't do it, because you don't store the pointer. That means the called function must do it, but that's not clear to someone looking at that function. Similarly, if I call the code from somewhere else, I certainly don't expect the function to call delete on the pointer I passed to it!
If we make your example slightly more complex, it can leak memory, even if the called function calls delete. Say it looks like this: functionCall(new className(initializers), new className(initializers)); Imagine that the first one is allocated successfully, but the second one throws an exception (maybe it's out of memory, or maybe the class constructor threw an exception). functionCall never gets called then, and can't free the memory.
The simple (but still messy) solution is to allocate memory first, and store the pointer, and then free it in the same scope as it was declared (so the calling function owns the memory):
className* p = new className(initializers);
functionCall(p);
delete p;
But this is still a mess. What if functionCall throws an exception? Then p won't be deleted. Unless we add a try/catch around the whole thing, but sheesh, that's messy.
What if the function gets a bit more complex, and may return after functionCall but before delete? Whoops, memory leak. Impossible to maintain. Bad code.
So one of the nice solutions is to use a smart pointer:
boost::shared_ptr<className> p = boost::shared_ptr<className>(new className(initializers));
functionCall(p);
Now ownership of the memory is dealt with. The shared_ptr owns the memory, and guarantees that it'll get freed. We could use std::auto_ptr instead, of course, but shared_ptr implements the semantics you'd usually expect.
Note that I still allocated the memory on a separate line, because the problem with making multiple allocations on the same line as you make the function call still exists. One of them may still throw, and then you've leaked memory.
Smart pointers are generally the absolute minimum you need to handle memory management.
But often, the nice solution is to write your own RAII class.
className should be allocated on the stack, and in its constructor, make what allocations with new are necessary. And in its destructor, it should free that memory. This way, you're guaranteed that no memory leaks will occur, and you can make the function call as simple as this:
functionCall(className(initializers));
The C++ standard library works like this. std::vector is one example. You'd never allocate a vector with new. You allocate it on the stack, and let it deal with its memory allocations internally.
Yes, as long as you deallocate the memory inside the function. But by no means this is a best practice for C++.
It depends.
This passes "ownership" of the memory to functionCAll(). It will either need to free the object or save the pointer so that it can be freed later. Passing the ownership of raw pointers like this is one of the easiest ways to build memory issues into your code -- either leaks or double deletes.
In C++ we would not create the memory dynamically like that.
Instead you would create a temporary stack object.
You only need to create a heap object via new if you want the lifetime of the object to be greater than the call to the function. In this case you can use new in conjunction with a smart pointer (see other answers for an example).
// No need for new or memory management just do this
functionCall(className(initializers));
// This assumes you can change the functionCall to somthing like this.
functionCall(className const& param)
{
<< Do Stuff >>
}
If you want to pass a non const reference then do it like this:
calssName tmp(initializers);
functionCall(tmp);
functionCall(className& param)
{
<< Do Stuff >>
}
It is safe if the function that you are calling has acceptance-of-ownership semantics. I don't recall a time where I needed this, so I would consider it unusual.
If the function works this way, it should take its argument as a smart pointer object so that the intent is clea; i.e.
void functionCall(std::auto_ptr<className> ptr);
rather than
void functionCall(className* ptr);
This makes the transfer of ownership explicit, and the calling function will dispose of the memory pointed to by ptr when execution of the function falls out of scope.
This will work for objects created on the stack, but not a regular pointer in C++.
An auto pointer maybe able to handle it, but I haven't messed with them enough to know.
In general, no, unless you want to leak memory. In fact, in most cases, this won't work, since the result of
new T();
in C++ is a T*, not a T (in C#, new T() returns a T).
Have a look at Smart Pointers or A garbage collector for C and C++.
I have been working on some legacy C++ code that uses variable length structures (TAPI), where the structure size will depend on variable length strings. The structures are allocated by casting array new thus:
STRUCT* pStruct = (STRUCT*)new BYTE[sizeof(STRUCT) + nPaddingSize];
Later on however the memory is freed using a delete call:
delete pStruct;
Will this mix of array new[] and non-array delete cause a memory leak or would it depend on the compiler? Would I be better off changing this code to use malloc and free instead?
Technically I believe it could cause a problem with mismatched allocators, though in practice I don't know of any compiler that would not do the right thing with this example.
More importantly if STRUCT where to have (or ever be given) a destructor then it would invoke the destructor without having invoked the corresponding constructor.
Of course, if you know where pStruct came from why not just cast it on delete to match the allocation:
delete [] (BYTE*) pStruct;
I personally think you'd be better off using std::vector to manage your memory, so you don't need the delete.
std::vector<BYTE> backing(sizeof(STRUCT) + nPaddingSize);
STRUCT* pStruct = (STRUCT*)(&backing[0]);
Once backing leaves scope, your pStruct is no longer valid.
Or, you can use:
boost::scoped_array<BYTE> backing(new BYTE[sizeof(STRUCT) + nPaddingSize]);
STRUCT* pStruct = (STRUCT*)backing.get();
Or boost::shared_array if you need to move ownership around.
Yes it will cause a memory leak.
See this except from C++ Gotchas: http://www.informit.com/articles/article.aspx?p=30642 for why.
Raymond Chen has an explanation of how vector new and delete differ from the scalar versions under the covers for the Microsoft compiler... Here:
http://blogs.msdn.com/oldnewthing/archive/2004/02/03/66660.aspx
IMHO you should fix the delete to:
delete [] pStruct;
rather than switching to malloc/free, if only because it's a simpler change to make without making mistakes ;)
And, of course, the simpler to make change that I show above is wrong due to the casting in the original allocation, it should be
delete [] reinterpret_cast<BYTE *>(pStruct);
so, I guess it's probably as easy to switch to malloc/free after all ;)
The behaviour of the code is undefined. You may be lucky (or not) and it may work with your compiler, but really that's not correct code. There's two problems with it:
The delete should be an array delete [].
The delete should be called on a pointer to the same type as the type allocated.
So to be entirely correct, you want to be doing something like this:
delete [] (BYTE*)(pStruct);
The C++ standard clearly states:
delete-expression:
::opt delete cast-expression
::opt delete [ ] cast-expression
The first alternative is for non-array objects, and the second is for arrays. The operand shall have a pointer type, or a class type having a single conversion function (12.3.2) to a pointer type. The result has type void.
In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object [...] If not, the behavior is undefined.
The value of the operand in delete pStruct is a pointer to an array of char, independent of its static type (STRUCT*). Therefore, any discussion of memory leaks is quite pointless, because the code is ill-formed, and a C++ compiler is not required to produce a sensible executable in this case.
It could leak memory, it could not, or it could do anything up to crashing your system. Indeed, a C++ implementation with which I tested your code aborts the program execution at the point of the delete expression.
As highlighted in other posts:
1) Calls to new/delete allocate memory and may call constructors/destructors (C++ '03 5.3.4/5.3.5)
2) Mixing array/non-array versions of new and delete is undefined behaviour. (C++ '03 5.3.5/4)
Looking at the source it appears that someone did a search and replace for malloc and free and the above is the result. C++ does have a direct replacement for these functions, and that is to call the allocation functions for new and delete directly:
STRUCT* pStruct = (STRUCT*)::operator new (sizeof(STRUCT) + nPaddingSize);
// ...
pStruct->~STRUCT (); // Call STRUCT destructor
::operator delete (pStruct);
If the constructor for STRUCT should be called, then you could consider allocating the memory and then use placement new:
BYTE * pByteData = new BYTE[sizeof(STRUCT) + nPaddingSize];
STRUCT * pStruct = new (pByteData) STRUCT ();
// ...
pStruct->~STRUCT ();
delete[] pByteData;
#eric - Thanks for the comments. You keep saying something though, that drives me nuts:
Those run-time libraries handle the
memory management calls to the OS in a
OS independent consistent syntax and
those run-time libraries are
responsible for making malloc and new
work consistently between OSes such as
Linux, Windows, Solaris, AIX, etc....
This is not true. The compiler writer provides the implementation of the std libraries, for instance, and they are absolutely free to implement those in an OS dependent way. They're free, for instance, to make one giant call to malloc, and then manage memory within the block however they wish.
Compatibility is provided because the API of std, etc. is the same - not because the run-time libraries all turn around and call the exact same OS calls.
The various possible uses of the keywords new and delete seem to create a fair amount of confusion. There are always two stages to constructing dynamic objects in C++: the allocation of the raw memory and the construction of the new object in the allocated memory area. On the other side of the object lifetime there is the destruction of the object and the deallocation of the memory location where the object resided.
Frequently these two steps are performed by a single C++ statement.
MyObject* ObjPtr = new MyObject;
//...
delete MyObject;
Instead of the above you can use the C++ raw memory allocation functions operator new and operator delete and explicit construction (via placement new) and destruction to perform the equivalent steps.
void* MemoryPtr = ::operator new( sizeof(MyObject) );
MyObject* ObjPtr = new (MemoryPtr) MyObject;
// ...
ObjPtr->~MyObject();
::operator delete( MemoryPtr );
Notice how there is no casting involved, and only one type of object is constructed in the allocated memory area. Using something like new char[N] as a way to allocate raw memory is technically incorrect as, logically, char objects are created in the newly allocated memory. I don't know of any situation where it doesn't 'just work' but it blurs the distinction between raw memory allocation and object creation so I advise against it.
In this particular case, there is no gain to be had by separating out the two steps of delete but you do need to manually control the initial allocation. The above code works in the 'everything working' scenario but it will leak the raw memory in the case where the constructor of MyObject throws an exception. While this could be caught and solved with an exception handler at the point of allocation it is probably neater to provide a custom operator new so that the complete construction can be handled by a placement new expression.
class MyObject
{
void* operator new( std::size_t rqsize, std::size_t padding )
{
return ::operator new( rqsize + padding );
}
// Usual (non-placement) delete
// We need to define this as our placement operator delete
// function happens to have one of the allowed signatures for
// a non-placement operator delete
void operator delete( void* p )
{
::operator delete( p );
}
// Placement operator delete
void operator delete( void* p, std::size_t )
{
::operator delete( p );
}
};
There are a couple of subtle points here. We define a class placement new so that we can allocate enough memory for the class instance plus some user specifiable padding. Because we do this we need to provide a matching placement delete so that if the memory allocation succeeds but the construction fails, the allocated memory is automatically deallocated. Unfortunately, the signature for our placement delete matches one of the two allowed signatures for non-placement delete so we need to provide the other form of non-placement delete so that our real placement delete is treated as a placement delete. (We could have got around this by adding an extra dummy parameter to both our placement new and placement delete, but this would have required extra work at all the calling sites.)
// Called in one step like so:
MyObject* ObjectPtr = new (padding) MyObject;
Using a single new expression we are now guaranteed that memory won't leak if any part of the new expression throws.
At the other end of the object lifetime, because we defined operator delete (even if we hadn't, the memory for the object originally came from global operator new in any case), the following is the correct way to destroy the dynamically created object.
delete ObjectPtr;
Summary!
Look no casts! operator new and operator delete deal with raw memory, placement new can construct objects in raw memory. An explicit cast from a void* to an object pointer is usually a sign of something logically wrong, even if it does 'just work'.
We've completely ignored new[] and delete[]. These variable size objects will not work in arrays in any case.
Placement new allows a new expression not to leak, the new expression still evaluates to a pointer to an object that needs destroying and memory that needs deallocating. Use of some type of smart pointer may help prevent other types of leak. On the plus side we've let a plain delete be the correct way to do this so most standard smart pointers will work.
If you really must do this sort of thing, you should probably call operator new directly:
STRUCT* pStruct = operator new(sizeof(STRUCT) + nPaddingSize);
I believe calling it this way avoids calling constructors/destructors.
I am currently unable to vote, but slicedlime's answer is preferable to Rob Walker's answer, since the problem has nothing to do with allocators or whether or not the STRUCT has a destructor.
Also note that the example code does not necessarily result in a memory leak - it's undefined behavior. Pretty much anything could happen (from nothing bad to a crash far, far away).
The example code results in undefined behavior, plain and simple. slicedlime's answer is direct and to the point (with the caveat that the word 'vector' should be changed to 'array' since vectors are an STL thing).
This kind of stuff is covered pretty well in the C++ FAQ (Sections 16.12, 16.13, and 16.14):
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.12
It's an array delete ([]) you're referring to, not a vector delete.
A vector is std::vector, and it takes care of deletion of its elements.
You'd could cast back to a BYTE * and the delete:
delete[] (BYTE*)pStruct;
Yes that may, since your allocating with new[] but deallocating with delelte, yes malloc/free is safer here, but in c++ you should not use them since they won't handle (de)constructors.
Also your code will call the deconstructor, but not the constructor. For some structs this may cause a memory leak (if the constructor allocated further memory, eg for a string)
Better would be to do it correctly, as this will also correctly call any constructors and deconstructors
STRUCT* pStruct = new STRUCT;
...
delete pStruct;
It's always best to keep acquisition/release of any resource as balanced as possible.
Although leaking or not is hard to say in this case. It depends on the compiler's implementation of the vector (de)allocation.
BYTE * pBytes = new BYTE [sizeof(STRUCT) + nPaddingSize];
STRUCT* pStruct = reinterpret_cast< STRUCT* > ( pBytes ) ;
// do stuff with pStruct
delete [] pBytes ;
Len: the problem with that is that pStruct is a STRUCT*, but the memory allocated is actually a BYTE[] of some unknown size. So delete[] pStruct will not de-allocate all of the allocated memory.
You're sort of mixing C and C++ ways of doing things. Why allocate more than the size of a STRUCT? Why not just "new STRUCT"? If you must do this then it might be clearer to use malloc and free in this case, since then you or other programmers might be a little less likely to make assumptions about the types and sizes of the allocated objects.
#Matt Cruikshank
You should pay attention and read what I wrote again because I never suggested not calling delete[] and just let the OS clean up. And you're wrong about the C++ run-time libraries managing the heap. If that were the case then C++ would not be portable as is today and a crashing application would never get cleaned up by the OS. (acknowledging there are OS specific run-times that make C/C++ appear non-portable). I challenge you to find stdlib.h in the Linux sources from kernel.org. The new keyword in C++ actually is talking to the same memory management routines as malloc.
The C++ run-time libraries make OS system calls and it's the OS that manages the heaps. You are partly correct in that the run-time libraries indicate when to release the memory however, they don't actually walk any heap tables directly. In other words, the runtime you link against does not add code to your application to walk heaps to allocate or deallocate. This is the case in Windows, Linux, Solaris, AIX, etc... It's also the reason you won't fine malloc in any Linux's kernel source nor will you find stdlib.h in Linux source. Understand these modern operating system have virtual memory managers that complicates things a bit further.
Ever wonder why you can make a call to malloc for 2G of RAM on a 1G box and still get back a valid memory pointer?
Memory management on x86 processors is managed within Kernel space using three tables. PAM (Page Allocation Table), PD (Page Directories) and PT (Page Tables). This is at the hardware level I'm speaking of. One of the things the OS memory manager does, not your C++ application, is to find out how much physical memory is installed on the box during boot with help of BIOS calls. The OS also handles exceptions such as when you try to access memory your application does not have rights too. (GPF General Protection Fault).
It may be that we are saying the same thing Matt, but I think you may be confusing the under hood functionality a bit. I use to maintain a C/C++ compiler for a living...
#ericmayo - cripes. Well, experimenting with VS2005, I can't get an honest leak out of scalar delete on memory that was made by vector new. I guess the compiler behavior is "undefined" here, is about the best defense I can muster.
You've got to admit though, it's a really lousy practice to do what the original poster said.
If that were the case then C++ would
not be portable as is today and a
crashing application would never get
cleaned up by the OS.
This logic doesn't really hold, though. My assertion is that a compiler's runtime can manage the memory within the memory blocks that the OS returns to it. This is how most virtual machines work, so your argument against portability in this case don't make much sense.
#Matt Cruikshank
"Well, experimenting with VS2005, I can't get an honest leak out of scalar delete on memory that was made by vector new. I guess the compiler behavior is "undefined" here, is about the best defense I can muster."
I disagree that it's a compiler behavior or even a compiler issue. The 'new' keyword gets compiled and linked, as you pointed out, to run-time libraries. Those run-time libraries handle the memory management calls to the OS in a OS independent consistent syntax and those run-time libraries are responsible for making malloc and new work consistently between OSes such as Linux, Windows, Solaris, AIX, etc.... This is the reason I mentioned the portability argument; an attempt to prove to you that the run-time does not actually manage memory either.
The OS manages memory.
The run-time libs interface to the OS.. On Windows, this is the virtual memory manager DLLs. This is why stdlib.h is implemented within the GLIB-C libraries and not the Linux kernel source; if GLIB-C is used on other OSes, it's implementation of malloc changes to make the correct OS calls. In VS, Borland, etc.. you will never find any libraries that ship with their compilers that actually manage memory either. You will, however, find OS specific definitions for malloc.
Since we have the source to Linux, you can go look at how malloc is implemented there. You will see that malloc is actually implemented in the GCC compiler which, in turn, basically makes two Linux system calls into the kernel to allocate memory. Never, malloc itself, actually managing memory!
And don't take it from me. Read the source code to Linux OS or you can see what K&R say about it... Here is a PDF link to the K&R on C.
http://www.oberon2005.ru/paper/kr_c.pdf
See near end of Page 149:
"Calls to malloc and free may occur in any order; malloc calls
upon the operating system to obtain more memory as necessary. These routines illustrate some of the considerations involved in writing machine-dependent code in a relatively machineindependent way, and also show a real-life application of structures, unions and typedef."
"You've got to admit though, it's a really lousy practice to do what the original poster said."
Oh, I don't disagree there. My point was that the original poster's code was not conducive of a memory leak. That's all I was saying. I didn't chime in on the best practice side of things. Since the code is calling delete, the memory is getting free up.
I agree, in your defense, if the original poster's code never exited or never made it to the delete call, that the code could have a memory leak but since he states that later on he sees the delete getting called. "Later on however the memory is freed using a delete call:"
Moreover, my reason for responding as I did was due to the OP's comment "variable length structures (TAPI), where the structure size will depend on variable length strings"
That comment sounded like he was questioning the dynamic nature of the allocations against the cast being made and was consequentially wondering if that would cause a memory leak. I was reading between the lines if you will ;).
In addition to the excellent answers above, I would also like to add:
If your code runs on linux or if you can compile it on linux then I would suggest running it through Valgrind. It is an excellent tool, among the myriad of useful warnings it produces it also will tell you when you allocate memory as an array and then free it as a non-array ( and vice-versa ).
Use operator new and delete:
struct STRUCT
{
void *operator new (size_t)
{
return new char [sizeof(STRUCT) + nPaddingSize];
}
void operator delete (void *memory)
{
delete [] reinterpret_cast <char *> (memory);
}
};
void main()
{
STRUCT *s = new STRUCT;
delete s;
}
I think the is no memory leak.
STRUCT* pStruct = (STRUCT*)new BYTE [sizeof(STRUCT) + nPaddingSize];
This gets translated into a memory allocation call within the operating system upon which a pointer to that memory is returned. At the time memory is allocated, the size of sizeof(STRUCT) and the size of nPaddingSize would be known in order to fulfill any memory allocation requests against the underlying operating system.
So the memory that is allocated is "recorded" in the operating system's global memory allocation tables. Memory tables are indexed by their pointers. So in the corresponding call to delete, all memory that was originally allocated is free. (memory fragmentation a popular subject in this realm as well).
You see, the C/C++ compiler is not managing memory, the underlying operating system is.
I agree there are cleaner methods but the OP did say this was legacy code.
In short, I don't see a memory leak as the accepted answer believes there to be one.
Rob Walker reply is good.
Just small addition, if you don't have any constructor or/and distructors, so you basically need allocate and free a chunk of raw memory, consider using free/malloc pair.
ericmayo.myopenid.com is so wrong, that someone with enough reputation should downvote him.
The C or C++ runtime libraries are managing the heap which is given to it in blocks by the Operating System, somewhat like you indicate, Eric. But it is the responsibility of the developer to indicate to the compiler which runtime calls should be made to free memory, and possibly destruct the objects that are there. Vector delete (aka delete[]) is necessary in this case, in order for the C++ runtime to leave the heap in a valid state. The fact that when the PROCESS terminates, the OS is smart enough to deallocate the underlying memory blocks is not something that developers should rely on. This would be like never calling delete at all.