void foo(int i)
{
char* p = new char[10];
if (i)
{
p = 0;
}
delete[] p;
}
In the above code snippet, p resource was referenced to zero. Will this create a memory leak in my code?
Yes it leaks in case i != 0.
Your variable p points to some address in memory and by doing p = 0; you erase that pointer. So the instruction delete[] p; will work for a nullptr pointer and you'll not free the allocated memory.
For this type of problems we use smart pointers (unique_ptr, shared_ptr, ...) and STL containers and objects like std::string, std::vector<char>, std::list<char> and so on.
So, in your case you have to change code to something like that
{
char* p = new char[10];
if (i)
{
if (p) {
delete[] p;
p = 0;
}
}
if (p) {
delete[] p;
p = 0;
}
}
Inside your function foo, you are setting the value of the pointer p, which actually is a pointer to the beginning of your dynamic array, to 0 if i is non-zero:
if(i)
{
p = 0;
}
Therefore, when i is non-zero, p no longer points to the start of your array and the delete command will fail to deallocate the array that you create inside the function.
So yes, when i is non-zero, your function will leak memory. I wouldn't change p if I were you. Keep that unchanged until the end so that you call delete [] on it and deallocate the array.
Alternatively, consider using a std::vector instead:
std::vector<char> vec(10);
This does something equivalent except it will take care of the memory allocation/deallocation for you automatically.
Related
Consider that I have an array of pointers declared as:
MyObject** myArr = new MyObject*[someSize] ;
And then I assign some objects by
myArr[i] = myObjectInstance
Now, I want to delete every element pointed to by each pointer of this array. So what is the correct way to do that?
I don't think delete[] myArr works.
Delete each object first, then the whole array:
for(int i = 0; i < someSize; i++)
{
delete myArr[i];
}
delete[] myArr;
You can use the standard algorithm std::for_each and the function object std::default_delete.
Here is a demonstrative program
#include <iostream>
#include <memory>
#include <algorithm>
struct A
{
static size_t i;
A() { i++; }
~A() { std::cout << --i << ": ~A()\n"; }
};
size_t A::i = 0;
int main()
{
const size_t N = 10;
A **p = new A *[N];
for ( size_t i = 0; i < N; i++ )
{
p[i] = new A();
}
std::for_each( p, p + N, std::default_delete<A>() );
delete []p;
return 0;
}
Its output is
9: ~A()
8: ~A()
7: ~A()
6: ~A()
5: ~A()
4: ~A()
3: ~A()
2: ~A()
1: ~A()
0: ~A()
If you want to delete the elements of the array in the reverse order relative to the order of creating them then you can write
std::for_each( std::reverse_iterator<A **>( p + N ),
std::reverse_iterator<A **>( p ), std::default_delete<A>() );
for (int i = 0; i < someSize; ++i)
delete myArr[i];
That could do the trick. However you go about it, you will have to visit each element and delete it individually, and then delete the array with delete [] myArr;.
But dynamically allocating arrays can be messy business. In keeping up with SO traditions, I'm going to recommend std::vector (or whatever STL container makes sense) if you are able to use it. You would still have to individually delete all elements, but now you don't have to worry about the array itself.
As mentioned in the comments to your question, if you use smart pointers to each element, then you don't have to manually delete anything.
Acctualy, delete[] myArr is right, because myArr is dynamically allocated object.
You might need to deallocate some myArr[i] before if you do any myArr[i] = myObjectInstance where myObjectInstance is dynamically allocated, example:
myArr[i] = new MyObject;
delete myArr[i]; is going to crash if:
MyObject m;
myArr[i] = &m;
In the case of all positions being dynamically allocated, you can use a for to free memory:
for (int i = 0; i < someSize; ++i)
delete myArr[i];
Let us assume that all the myObjectInstance are pointers to heap allocated objects (if not so, see #JoĆ£oPaulo 's answer), and no custom new or delete is involved.
for (size_t idx = 0; idx < someSize; ++idx)
delete myArr[idx];
delete[] myArr;
What is the potential pitfall?
Well, there are many. What if only some of the array elements are initialized? The other would be in an indetermined state, and deleting them leads to undefined behavior.
Also, what if multiple array elements points to the same object? Then you are trying to delete an object multiple times. That also leads to undefined behavior.
This doesn't mean you cannot use this naive method, it just reminds you of some pre-conditions:
Make sure every element of array is initialized to either "pointer to some heap allocated object" or nullptr (deleting nullptr is safe).
Make sure you don't delete an object twice.
I have a question on memory leak. Probably a basic one.
map_a is an map of <int, vector<int>*>
ptr is an pointer to an vector of ints.
Inside for loop, I am searching for 'element' in map_a. If pointer is not found, then create a new vector/record in map_a.
C++ pseudo-code:
map map_a;
for ( 1 to 10 ) {
element = <int number come from a different algorithm, diff every time>;
vector<int> *ptr = map_a[element];
if (!ptr) {
ptr = new vector<int>;
map[element] = ptr;
}
ptr->push_back(i);
}
How to free up the memory we are allocation using new? I am sure that we may be having alternate ways to achieve this situation. But how to take this code along? Are there alternatives?
Any pointer in c++ is deallocated just the same way. So if you have a pointer to a vector you can call delete like so:
vector<int> *a = new vector<int>();
delete a;
However I think that most probably there is a better solution to whatever you are trying to do than using a dynamically allocated vector.
EDIT: from your question it is not apparent if the map is empty before the cycle. If it is you can simply iterate over it and call delete for each of its values:
for (auto it = map_a.begin(); it != map_a.end(); ++it) {
delete it->second.
}
However if the map is not empty you will need an auxilary container (say a vector) to store the pointers allocated in this cycle:
map map_a;
vector<vector<int> * > allocated;
for ( 1 to 10 ) {
element = <int number come from a different algorithm, diff every time>;
vector<int> *ptr = map_a[element];
if (!ptr) {
ptr = new vector<int>;
allocated.push_back(ptr);
map[element] = ptr;
}
ptr->push_back(i);
}
for (int i = 0; i < allocated.size(); ++i) {
delete allocated[i];
}
I would like to have a dynamic array of pointers to pointers to Pair elements;
int m_size = 0;
Pair** ar = new Pair*[++m_size];
*ar[0] = Pair(key, data);
Here I get:
Unhandled exception at 0x013729db in lab3.exe: 0xC0000005: Access violation writing location 0xcdcdcdcd.
It happened in the overloaded operator for MyString (HERE marks when the exception threw):
MyString & MyString::operator = (const MyString & refMyString){
HERE: this->m_pStr = refMyString.m_pStr;
return *this;
}
My classes (a bit simplified for our purpose):
class Pair{
MyString m_key;
Data* m_data;
}
class MyString
{
char* m_pStr;
}
And here is what I get in the debugger:
http://sdrv.ms/ZwkZ9P
http://sdrv.ms/17eoGp6
Well, as far as I can see, when I did Pair** ar = new Pair*[++m_size], a new pointer to pointer to a space for a Pair instance was created. But it is just space in memory. And when I try to operate it, I fail.
And what to do is a mystery to me. Could you help me?
You allocate an array of Pair* but :
1) You never initialize the pointers in that array
2) You dereference those uninitialized pointers (which point to who-knows-where) and overwrite the memory there.
No wonder you get a segfault since you're writing to unallocated memory.
What you (probably?) want to do is:
ar[0] = new Pair(...)
Or better yet, use a standard container (vector, list, deque, ...) instead of C arrays, that will either contain plain objects or smart pointers (unique_ptr or shared_ptr) so that you don't have to manage the memory yourself.
When creating a two dimensional array using a double pointer, you need to allocate both dimensions:
// allocates an array of 10 int* objects
int** p = new int*[10];
for(int x = 0; x < 10; ++x)
{
// Allocates an array of 3 integers
p[0] = new int[3];
}
You would need to ensure that all of the objects you are creating are deleted:
// later
for(int x = 0; x < 10; ++x)
delete [] p[x];
delete [] p;
I would suggest however, just using std::vector so you don't need to manage the memory yourself:
std::vector<std::vector<int>> p;
p.resize(10);
for(int x = 0; x < 10; ++x)
{
p[x].resize(3);
}
Consider this code:
using namespace std;
int* get()
{
unique_ptr<int> p (new int[4]);
return p.get();
}
int main(int argc, char **argv)
{
int *arr1=get();
int* arr2=get();
for(int i=0;i<4;i++)
{
arr1[i]=i;
arr2[i]=i*2;
}
for(int i=0;i<4;i++)
cout << arr1[i];
return 0;
}
arr1 and arr2 point to the same area of memory.
So they share the same values.
I don't understand why, when I call arr2=get() :
unique_ptr<int> p (new int[4]);
This object shouldn't be created again? It isn't deleted because still reachable by arr1.
How to get two arrays of different memory areas?
I am fairly sure you are playing with undefined behavior which is bad.
the data being pointed to was destroyed when the unique pointer was destroyed, the fact the values are the same, and the same slot was chosen is luck.
for pointers to array type use a vector
std::vector<int> get()
{
return std::vector<int>(4);
}
int main()
{
std::vector<int> arr1=get();
std::vector<int> arr2=get();
return 0;
}
for normal single value pointers then you can return a unique_ptr;
std::unique_ptr<int> get(){
return std::unique_ptr<int>(new int(0));
}
:::
std::unique_ptr<int> ptr=get();
There are a memory leak in such kind of usage of smart pointers. unique_ptr will use operator delete in order to free the allocated memory, but you need delete []. Also the return value of get function will be an invalid ptr because the unique_ptr will free the allocated area. If you need dynamically allocated arrays then use std::vector.
struct item
{
unsigned int a, b, c;
};
item* items[10];
delete items[5];
items[5] = NULL;
The above code works
But the below method is not working
int * arr1[30];
delete (arr1+5);
I am a beginner, Please tell me why I am able to delete in case of structure pointer but not in case of int
pointer
You're seemingly misunderstanding what delete is for: it's purely and simply to release memory allocated by new, not to 'delete' elements of arrays.
So you might use it like this:
int *p = new int;
//...
delete p;
When you allocate arrays, you must instead use delete[], like this:
int *q = new int[23];
//...
delete [] q;
But at no point should you try and delete something that hasn't been new'ed, or use the non-matching version of delete, e.g. delete [] p; or delete q; above.
If what you really want is some sort of 'array' from which you can remove elements, try this:
#include <vector>
struct item
{
unsigned int a, b, c;
};
int main()
{
std::vector<item> items(10);
items[5].a = 23;
items.erase(items.begin() + 5);
return 0;
}
Are you allocating heap memory anywhere? You are not doing so in the code above. You are lucky that the first delete does not crash.
When using the (arr1+5) approach, you are passing the memory address of the array slot itself at index 5, not the int* that the slot contains. To delete the int* that is contained in the slot at index 5, you have to dereference the pointer value, eg:
delete *(arr1+5);