If I have a function like:
void MyFunctoin(int size){
// ...
int *arr=new int[size];
// ...
}
Is there a memory leak?
If yes, is there a way to solve it without using delete?
The answer to your title question is simple: yes, every new must be matched by a delete. In your case, since you used new[], there must be a delete[] somewhere.
But you don't need to write it yourself. It is usually much better to use a class that manages its own resources. In your case, you'd be better off using an STL container such as array<> or vector<>. This is, either:
std::array<int, size> arr; // fixed size (known at compile time)
or
std::vector<int> arr; // variable size
In vector, all the necessary calls to new and delete are done inside the container and you needn't care about them.
You could write your function this way:
#include <vector>
void MyFunctoin(int size){
// ...
std::vector<int> arr(size);
// ...
}
and there would not be any memory leak with no need to call delete anywhere. You don't need to specify size when constructing arr if you don't want to.
Yes, it is. Use smart pointers/STL containers (for example std::vector/boost::shared_array/std::unique_ptr<T[]> in your case).
There is a leak if the ... part after the arr = new does not contain a delete [] arr, yes.
The solution is to either add a delete [] arr at a suitable point, or use vector<int> arr(size);, or unique_ptr<int[]> arr(new int[size]).
Which is the "right" choice really depends on what you are overall trying to achieve.
Yes. but you can use below smart pointer to get rid of that:
std::unique_ptr<int[]> arr (new int[size]);
Yes. You need to match up each new with a delete, and each new[] with a delete[].
There are two alternatives. The first is to use a garbage collecting library such as the well-known Boehm GC.
The second, better solution is to use smart pointers. These will call delete for you at the appropriate time. There are a couple in the C++ standard library, and Boost has lots more that cover just about every possible use-case.
As already pointed out, all news must have matching deletes somewhere. Smart pointers conveniently handle this for you.
Another, non-C++ solution that might apply here would be to not use new, but alloca from the standard C library. This is more lightweight and you don't have to deallocate, but of course you can blow up the stack if size gets too big.
yes.
use a smart pointer
template<class C> struct smartpointer
{
C* data;
smartpointer():data(NULL){}
~smartpointer(){if(data){delete data;data=NULL;}
};
this automatically destroy its content when the block expires
Related
So let's say that you wanted to make a realloc function in C++. I imagine it can work something like this:
template<typename T>
void realloc(T** arr, int size, int original_size){
T *newArr = new T[size];
for(int i = 0; i<original_size;i++)
newArr[i] = (*arr)[i];
delete[] *arr;
*arr = newArr;
}
Now my question is wheter it is correct to use delete[] here? From what I know allocated memory size is tracked at runtime so C++ knows how much to delete. Is that preserved when passing it like this or are there better ways of doing this?
Now my question is wheter it is correct to use delete[] here?
Yes, as long as *arr was allocated using new[].
From what I know allocated memory size is tracked at runtime so C++ knows how much to delete. Is that preserved when passing it like this [...]?
I'm not really sure what you mean here. The runtime keeps track of memory allocations, yes. But you have to be explicit about using delete[] for arrays (like new int[10]) and delete for non-arrays (like new MyClass()).
or are there better ways of doing this?
Using raw pointers should be avoided, even naked new is considered bad practice these days. Smart pointers and STL-containers like std::vector are superior alternatives for almost every scenario.
I want to create a vector of data, but I want to both set it's size and fill its elements in a sub-function. Is this an appropriate time to use the new operator? Is there a better way to do it? It seems like an appropriate time, but I'm hesitant because of Why should C++ programmers minimize use of 'new'?
int main()
{
vector<double> *array1;
vector<double> *array2;
OtherArgs otherArgs;
FillArrays(array1,array2,otherArgs);
//Do other stuff
delete array1;
delete array2;
}
void FillArrays(vector<double> *&array1, vector<double> *&array2, OtherArgs &otherArgs)
{
int size=GetSize(otherArgs);
array1 = new vector<double>(size);
array2 = new vector<double>(size);
//Other code to fill the arrays
}
Thank you
Here are a couple of reasons why the original sample is troublesome
The code leaks memory in the face of an exception because the delete calls aren't protected
If FillArrays is passed a non-NULL vectory<double> value it will leak memory because it didn't delete the previous value. It couldn't reliably call delete even if it wanted to because the value may have been stack allocated.
The easiest way to do this is to just declare the values on the stack and pass them by reference that way.
int main()
{
vector<double> array1;
vector<double> array2;
OtherArgs otherArgs;
FillArrays(array1,array2,otherArgs);
//Do other stuff
}
void FillArrays(vector<double> &array1, vector<double> &array2, OtherArgs &otherArgs)
{
int size=GetSize(otherArgs);
//Other code to fill the arrays
}
The vector<T> will initialize themselves to an empty list when declared in this manner. The FillArrays method can then populate them as necessary.
No, this is a specifically bad use of new.
If you must use new and delete1, use them as bookends. The delete expression should be in a logically consistent context with the new expression.
So, if you new in a c-tor, you should delete in the d-tor. If you new in an allocation function, you should delete in a deallocation function. The two calls should be arranged in an way that makes it obvious that one starts an operation and the other finishes it.
This implies that the call to new and delete should exist in the same layer in a functional or object hierarchy. Specifically, new and delete should be seen as implementation details, and not as part of the API contract.2
In your case, the new and delete are in entirely distinct contexts. new is inside the implementation, while delete is called for in the client. This will lead to programming errors.
Beyond that, the non-new version of your code (creating empty vectors in main, and passing them by reference) is simpler, easier to read, and more exception-friendly than the new version.
No, this is not a good example of when to use new. It is, however, an excellent example of when not to.
1 You hardly ever need to use new and delete. If you need dynamic allocation, just let containers keep copies of your objects.
2 std::shared_ptr, et al, violate this rule -- the new and delete are specifically part of the contract. This is probably OK, since pointer manipulation is their reason for existence. But SO has seen its share of bugs about storing a non-new pointer in shared_ptr.
Hi there i have some questions about pointers and arrays in c++:
when i want to pass an array of pointers in a function i must write:
foo(test *ptest[])
right?
when i want to delete a array of pointers, does
delete ptest;
all for me?
when i pass a pointer to another class and the first class make a delete, the pointer is deletete in all classes right?
must i always create a array of a constant size?
First of all, forget about arrays and pointers and tell us what you really want to achieve. You are probably better off using std::vector<T> and pass that around by (const) reference, saving you all the headaches of manual resource management and crazy array-to-pointer-decay rules inherited from C.
Now to answer your questions:
when i want to pass an array of pointers in a function i must write:
foo(test *ptest[])
right?
Yes, but remember that array parameters are always rewritten by the compiler to pointers. Your code is equivalent to:
foo(test **ptest)
This means that all information about the size of the array has been lost. Moving on:
when i want to delete a array of pointers, does
delete ptest;
all for me?
No. If you acquire via new[], you must release via delete[], otherwise you get undefined behavior. Note that deleting an array of pointers only gets rid of the array itself, not any objects pointed to by the pointers stored inside the array.
Again: Forget about arrays and pointers and use the facilities provided by the C++ standard library.
when i want to delete a array of pointers, does delete ptest; all for me?
Nope. It tries to delete what's been allocated to the address ptest. If ptest is not something which was allocated dynamically, your program will crash. You can only call delete on the addresses which you have received from new.
when i pass a pointer to another class and the first class make a delete, the pointer is deletete in all classes right?
Nope, you need to have exactly one delete for every new. (yah, there are "smart pointers" which call delete for you, but the point still holds.)
must i always create a array of a constant size?
Nope. In C++ there's std::vector for having arrays of dynamic size (can be used for constant-size arrays too) and in C there's realloc for changing a size of an array.
To delete any array you need:
delete [] ptest; // note the [] part
Arrays can be any size you like (within various practical limits) and unless you make copies of an array then you should delete it exactly once (it doesn't matter where you do this, so long as you don't try to acess the data afterwards).
Chances are, without knowing what you're aiming at and any other contextual information, you should use std::vector<T> instead and forget about these worries.
That said, to delete any primitive array arr you must say
delete[] arr;
Of course, if the pointers in the array themselves are each the last pointing at heap memory then you should free them first. You can do that nicely with a reusable Delete functor:
struct Delete {
template<class P>
void operator()(P ptr) const { delete ptr; }
};
// ...
std::foreach(arr, arr+ARR_LENGTH, Delete());
delete[] arr;
You must of course make sure no two pointers point at the same address. To further simplify things beyond what a std::vector<T> can do for you you should consider using a boost::shared_ptr<T>; this will allow you to forget about the delicate case in which two pointers point at the same address.
I come from a java background and there's something I could do in Java that I need to do in C++, but I'm not sure how to do it.
I need to declare an array, but at the moment I don't know the size. Once I know the size, then I set the size of the array. I java I would just do something like:
int [] array;
then
array = new int[someSize];
How do I do this in C++?
you want to use std::vector in most cases.
std::vector<int> array;
array.resize(someSize);
But if you insist on using new, then you have do to a bit more work than you do in Java.
int *array;
array = new int[someSize];
// then, later when you're done with array
delete [] array;
No c++ runtimes come with garbage collection by default, so the delete[] is required to avoid leaking memory. You can get the best of both worlds using a smart pointer type, but really, just use std::vector.
In C++ you can do:
int *array; // declare a pointer of type int.
array = new int[someSize]; // dynamically allocate memory using new
and once you are done using the memory..de-allocate it using delete as:
delete[]array;
Best way would be for you to use a std::vector. It does all you want and is easy to use and learn. Also, since this is C++, you should use a vector instead of an array. Here is an excellent reason as to why you should use a container class (a vector) instead of an array.
Vectors are dynamic in size and grow as you need them - just what you want.
The exact answer:
char * array = new char[64]; // 64-byte array
// New array
delete[] array;
array = new char[64];
std::vector is a much better choice in most cases, however. It does what you need without the manual delete and new commands.
As others have mentioned, std::vector is generally the way to go. The reason is that vector is very well understood, it's standardized across compilers and platforms, and above all it shields the programmer from the difficulties of manually managing memory. Moreover, vector elements are required to be allocated sequentially (i.e., vector elements A, B, C will appear in continuous memory in the same order as they were pushed into the vector). This should make the vector as cache-friendly as a regular dynamically allocated array.
While the same end result could definitely be accomplished by declaring a pointer to int and manually managing the memory, that would mean extra work:
Every time you need more memory, you must manually allocate it
You must be very careful to delete any previously allocated memory before assigning a new value to the pointer, lest you'll be stuck with huge memory leaks
Unlike std::vector, this approach is not RAII-friendly. Consider the following example:
void function()
{
int* array = new int[32];
char* somethingElse = new char[10];
// Do something useful.... No returns here, just one code path.
delete[] array;
delete[] somethingElse;
}
It looks safe and sound. But it isn't. What if, upon attempting to allocate 10 bytes for "somethingElse", the system runs out of memory? An exception of type std::bad_alloc will be thrown, which will start unwinding the stack looking for an exception handler, skipping the delete statements at the end of the function. You have a memory leak. That is but one of many reasons to avoid manually managing memory in C++. To remedy this (if you really, really want to), the Boost library provides a bunch of nice RAII wrappers, such as scoped_array and scoped_ptr.
use std::array when size is known at compile time otherwise use std::vector
#include <array>
constexpr int someSize = 10;
std::array<int, someSize> array;
or
#include <vector>
std::vector<int> array; //size = 0
array.resize(someSize); //size = someSize
Declare a pointer:
int * array;
I'm working on a section of code that has many possible failure points which cause it to exit the function early. The libraries I'm interacting with require that C-style arrays be passed to the functions. So, instead of calling delete on the arrays at every exit point, I'm doing this:
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength]);
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
I wanted to use unique_ptr, but my current compiler doesn't support it and the reference count overhead doesn't really matter in this case.
I'm just wondering if anyone has any thoughts on this practice when interfacing with legacy code.
UPDATE I completely forgot about the shared_ptr calling delete instead of delete []. I just saw no memory leaks and decided to go with it. Didn't even think to use a vector. Since I've been delving into new (for me) C++ lately I'm thinking I've got a case of the "If the only tool you have is a hammer, everything looks like a nail." syndrome. Thanks for the feedback.
UPDATE2 I figured I'd change the question and provide an answer to make it a little more valuable to someone making the same mistake I did. Although there are alternatives like scoped_array, shared_array and vector, you can use a shared_ptr to manage scope of an array (but after this I have no idea why I would want to):
template <typename T>
class ArrayDeleter
{
public:
void operator () (T* d) const
{
delete [] d;
}
};
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>());
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
Do not use shared_ptr or scoped_ptr to hold pointers to dynamically allocated arrays. shared_ptr and scoped_ptr use delete ptr; to clean-up when the pointer is no longer referenced/goes out of scope, which invoked undefined behaviour on a dynamically allocated array. Instead, use shared_array or scoped_array, which correctly use delete[] ptr; when destructing.
To answer your question, if you are not going to pass the smart pointer around, use scoped_array, as it has less overhead than shared_array.
Alternatively, use std::vector as the array storage (vectors have guaranteed contiguous memory allocation).
Use boost::scoped_array, or even better std::vector if you are dealing with an array.
I highly recommend simply using a std::vector. Elements in vectors are allocated on the heap, and will be deleted when the vector goes out of scope, wherever you exit the function.
In order to pass a vector to legacy code requiring C-style arrays, simply pass &vectorName[0]. The elements are guaranteed to be contiguous in memory.
Some remarks for C++11 users:
For shared_ptr, there is in C++11 a default deleter for array types defined in <memory> and standard compliant (wrt the final draft) so it can be used without additional fancy deleters for such cases:
std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>());
unique_ptr in C++11 has a partial specialization to deal with new[] and delete[]. But it does not have a shared behavior, unfortunately. Must be a good reason there is no such specialization for shared_ptr but I didn't look for it, if you know it, please share it.
There's boost::scoped_ptr for this.
This
shared_ptr<char*> raiiArray(new char[arrayLength]);
is not a good practice, but causes undefined behaviour, as you allocate with operator new[], but shared_ptr uses operator delete to free the memory. The right thing to use is boost::shared_array or add a custom deleter.