int* func()
{
int* i=new int[1];
//do something
return i;
}
void funcc()
{
int* tmp=func();
//delete allocated memory after use
delete tmp;
}
should delete working as described in the second function be a correct use ?
I think I didn't allocate memory to it by new ? new was used in the first, to be sure.
It should be delete [] tmp; because you're doing array new, but otherwise, it's correct.
As others have stated, you should use delete[] to delete arrays, not delete.
But, if you're asking whether it's okay to delete tmp because the memory it points to wasn't allocated with new, then your premise is incorrect.
It was allocated with new. The address of the memory that you allocate within the function for i is passed back to be stored in tmp, so it does point to memory that was allocated by new.
You're correct that i itself is out of scope at that point but memory allocated by new survives the scope change on exit from the function. And, since you're storing its location into tmp, you still have access to it.
Hence the deletion (once you make it an array deletion with []) is quite valid.
This is Undefined Behaviour™. You can only use delete if you used new. If you used new[], you MUST delete[] it. More than that, this is hideously unsafe code- you need a smart pointer.
No. new T[] should match delete []t. And new T should match delete t. Otherwise, your code would invoke undefined bevavior.
And it doesn't matter if you do delete []tmp outside the function. Its okay to do so. All that you need to keep in mind that the form of delete.
My spidey-senses tell me that you're wondering whether the dynamically-allocated int that you create in func is the same one that you attempt to delete in funcc.
The answer is: yes. Although you don't use strictly the same pointer variable, both pointers point to the same object.
However, please remember to use delete[] (with the []) when you used new[] (with the []). Your code is broken until you fix this.
Also, try to avoid newing in one place and deleteing in another. Perhaps consider a std::vector instead, which is far less error-prone.
Related
Must I use operator delete for stack pointer?
For example:
User * p = new User;
delete p; //needed?
When you use delete you are not deleting the pointer, so it makes no difference whether it is a stack pointer or any other kind of pointer.
When you use delete you are deleting the block of memory pointed by the pointer. If that block was allocated with new, then it's always on the heap. (If it was not allocated with new, then you should not delete it.)
The other angle is that no, you must not use operator delete, because you should never use naked pointers in non-library code.
In modern C++, your example should be:
std::unique_ptr<User> p = std::make_unique<User>();
No delete and no new in sight.
Note: in this particulate case, make_unique could be substituted for new painlessly, but since in other examples it might not be, it's a good practice to teach yourself - make_unique is a function to use.
I have a class pointer declaration:
MyClass* a;
In destruction method I have:
if (a)
{
delete a;
a= NULL;
}
I got a problem when delete the pointer a:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
What is the cause of the problem and how can I get rid of it?
With your current declaration:
MyClass* a;
a gets a random value. If you never give it a valid value later, such as:
a = new MyClass();
It will point to an unknown place in memory, quite probably not a memory area reserved for your program, and hence the error when you try to delete it.
The easiest way to avoid this problem is to give a a value when you declare it:
MyClass* a = new MyClass();
or, if you cannot give it a value when you declare it (maybe you don't know it yet), assign it to null:
MyClass* a = 0;
By the way, you can remove the test (if (a)) from your code. delete is a no-op on a null pointer.
Use smart pointer to free memory. delete in application code is always wrong.
unless you have initialized the pointer to something after this:
MyClass* a;
the pointer a will hold some random value. So your test
if (a) { }
will pass, and you attempt to delete some random memory location.
You can avoid this by initializing the pointer:
MyClass* a = 0;
Other options are that the object pointed to has been deleted elsewhere and the pointer not set to 0, or that it points to an object that is allocated on the stack.
As has been pointed out elsewhere, you could avoid all this trouble by using a smart pointer as opposed to a bare pointer in the first place. I would suggest having a look at std::unique_ptr.
How did you allocate the memory that a points to? If you used new[] (in order to create an array of MyClass), you must deallocate it with delete[] a;. If you allocated it with malloc() (which is probably a bad idea when working with classes), you must deallocate it with free().
If you allocated the memory with new, you have probably made a memory management error somewhere else - for instance, you might already have deallocated a, or you have written outside the bounds of some array. Try using Valgrind to debug memory problems.
You should use
MyClass* a = NULL;
in your declaration. If you never instantiate a, the pointer is pointing to an undefined region of memory. When the containing class destructor executes, it tries to delete that random location.
When you do MyClass* a; you declare a pointer without allocating any memory. You don't initialize it, and a is not necessarily NULL. So when you try to delete it, your test if (a) succeeds, but deallocation fails.
You should do MyClass* a = NULL; or MyClass* a(nullptr); if you can use C++11.
(I assume here you don't use new anywhere in this case, since you tell us that you only declare a pointer.)
Why is there a delete[]? From my understanding its to behave differently for arrays. However, why does it really exist? There's only free in C and no free_array. Also in syntax the only difference between delete var and delete []var is the [] which has no params (I'm not telling the length of the array).
So why does delete[] really exist? I know someone will say you can overload delete and delete[] (at least i think that is possible) but lets say we are not overloading it. Why does it exist?
Typically, for non-POD classes, a delete[] expression must call destructors on a variable number of class instances that cannot be determined at compile time. The compiler typically has to implement some run time "magic" that can be used to determine the correct number of objects to destroy.
A delete expression doesn't have to worry about this, it simply has to destroy the one object that the supplied pointer is pointing to. Because of this, it can have a more efficient implementation.
By splitting up delete and delete[], delete can be implemented without the overhead needed to correctly implement delete[] as well.
If you delete an array, only first object's destructor will be called. delete[] calls destructors of all objects in array and frees array's memory.
Assume delete[] didn't exist, write the code for deleting the array vs deleting only the first element in the array.
delete array; // Deletes first element, oops
delete &array; // Deletes first element, oops
delete &array[0]; // Deletes first element
A pointer to an array being an alias for a pointer to the first element of the array is of course an old C "feature".
Consider:
int* a = new int[25];
int* b = a;
delete b; // only deletes the first element
The C++ compiler has no idea whether b points to an array or a single element. Calling delete on an array will only delete the first element.
char *pointer1;
char *pointer2;
pointer1 = new char[256];
pointer2 = pointer1;
delete [] pointer1;
In other words, do I have to do delete [] pointer2 as well?
Thanks!
Nope, that code is fine and won't leak memory.
You only have to use delete[] once because you've only used one new to allocate an area for memory, even though there are two pointers to that same memory.
A simple rule: you need as many deletes as there are news. Even better, use something like a smart pointer or a container to take care of it for you.
And another minor point: pointer2 is becoming a "dangling pointer" once you call delete on pointer1.
It's not a leak, but it is asking for trouble. pointer2 is pointing to who-knows-what as soon as you delete pointer1. It's what's called a "dangling pointer". Using it can in the best case cause a segfault, and in the worst case can cause mysterious data mangling in anything that ends up allocated that same spot.
While it doesn't leak memory, if you want to be explicit, you should set both point1 and point2 to NULL (and initialize them that way too.)
Additionally, consider using boost::shared_ptr<> from the Boost libraries. It's the greatest thing since sliced bread.
typedef boost::shared_ptr<TypeX> StrRef;
foo() {
StrRef pointer1(new TypeX);
while(something) {
StrRef pointer2 = pointer1;
// do stuff
}
return;
}
The data (TypeX) will be deleted when the last pointer to it goes out of scope. You can do something similar with the built-in auto_ptr<> type, if you don't need a reference count:
typedef auto_ptr<TypeX> StrRef;
foo() {
StrRef pointer1(new TypeX);
while(something) {
TypeX * pointer2 = pointer1.get();
subroutine(pointer2);
if (condition) return;
}
return;
}
Whenever pointer1 goes out of scope, it will delete the data. The advantage with this is that you don't have to remember put a delete before the return statement at the bottom, and if pointer1 goes out of scope for any other reason (i.e. return from the middle of the loop, or subroutine() throws an exception, then the data will still be deallocated properly.
I haven't tested this code, so you'll have to check the docs for auto_ptr<> and boost::shared_ptr<> yourself.
I highly recommend using the Boost libraries as much as possible. It's written by pro's it's basically a staging area for extensions to C++.
delete deletes the memory that was allocated by new. Since you only have one new you only need one delete.
Only use Delete when you've used New
Good practive is to set pointer2 to NULL, but you won't have a memory leak if you don't
Every new should have one, and only one, matching delete. If you deleted the other pointer, you would break that rule.
What you do here is just tell that memory block allocated by new char[256] would be pointed by pointer1 and pointer2 at the same moment.
It would be a memory leak if you wrote delete[] pointer2; statement after.
No, you do not have to delete[] pointer2 because you have not allocated memory for it!
The statement pointer2 = pointer1 makes pointer2 point to the same memory address as pointer1, does not allocate any extra memory for it.
Here's the gap in your thinking: You don't delete pointers — you delete memory. You simply use a pointer to identify the block of memory to be freed. Since the two variables point to the same memory, deleting one is precisely equivalent to deleting the other. In other words, deleting both is the same as deleting one of them twice — which is obviously wrong.
I have a struct like this:
class Items
{
private:
struct item
{
unsigned int a, b, c;
};
item* items[MAX_ITEMS];
}
Say I wanted to 'delete' an item, like so:
items[5] = NULL;
And I created a new item on that same spot later:
items[5] = new item;
Would I still need to call delete[] to clean this up? Or won't this be needed since bounds of array items[] are known before compiling?
Is setting that pointer to NULL valid or should I be calling delete there?
You need to call delete before setting it to NULL. (Setting it to NULL isn't required, it just helps reduce bugs if you accidentally try to dereference the pointer after deleting it.)
Remember that every time you use new, you will need to use delete later on the same pointer. Never use one without the other.
Also, new [] and delete [] go together in the same way, but you should never mix new [] with delete or new with delete []. In your example, since you created the object with new (rather than new [] which would create an array of objects) you must delete the object with delete (rather than delete []).
As Kluge pointed out, you'd leak the object at index 5 like that. But this one really sounds like you shouldn't do this manually but use a container class inside Item. If you don't actually need to store these item objects as pointers, use std::vector<item> instead of that array of MAX_ITEMS pointers. You can always insert or erase vector elements in the middle as well if you need to.
In case you need to store the objects as pointers (usually if struct item is actually polymorphic, unlike in your example), you can use boost::ptr_vector<item> from Boost.PtrContainer instead.
Example:
class Items {
private:
struct item {
unsigned int a, b, c;
};
std::vector<item> items;
}
if (items.size() > 5) // (just to ensure there is an element at that position)
items.erase(items.begin() + 5); // no need to use operator delete at all
To delete an item use:
delete items[5];
after deleting the item it is advisable to set the deleted pointer to NULL, so you won't have an error if you later delete it again by mistake.
items[5] = NULL
Say I wanted to 'delete' an item, like so:
items[5] = NULL;
I know little Visual Basic, but that smells like a Visual Basic programming idiom, since "Set a = None" (or Null, I'm not sure) would delete the object pointed by a (or rather decrement its reference count, for COM objects).
As somebody else noted, you should use either:
delete items[5];
items[5] = newContent;
or:
delete items[5];
items[5] = NULL;
After delete[5], the only possible use of the pointer stored in items[5] is causing you trouble. What's worse is that it might happen to work at the beginning, and start failing only when you allocate something else over the space previously used by *items[5]. Those are the causes which make C/C++ programming "interesting", i.e. really annoying (even for who likes C like me).
Writing just delete items[5]; saves what can be an useless write, but that's a premature optimization.
Just to be clear: you refer to calling "delete[]". I think you mean delete.
I mention this because C++ has two separate operators, operator delete and operator delete[]. The latter is used for deleting arrays of objects allocated with operator new[], and does not apply in this case. You have an array of pointers to objects, which you must have initialised with repeated calls to operator new rather than a single call to operator new[].
All I'm really trying to say is: your use of delete[] is confusing and ambiguous; change it to delete.
There are a few, related, questions here:
According to the code you posted, the array itself is not allocated on the heap unless the struct is, so you don't need to delete[] the array. If you created the array with new[] you would have to delete[] it.
The code posted doesn't say how the objects being pointed to from the array are allocated. If you allocate those objects on the stack you must not delete them (then again, this is highly unlikely because your pointers will become invalid when the objects they point to fall out of scope). If you allocated them on the heap (with new) then you must delete them when they fall out of scope.
As others have already suggested, life is much easier if you use a container -- especially an STL container -- and smart pointers -- which for now means pointers out of Boost.
C++ isn't my strong suit, but I'm pretty sure you'd be leaking the memory if you set the pointer to NULL.
EDIT: The memory being leaked would be the memory being pointed to by the pointer in the array.
Setting items[5] to NULL doesn't delete the memory associated with the item, it simply sets the pointer to that item to NULL, therefore the memory is leaked.
You can delete the item by calling:
delete items[5];
Since C++ has not automatic garbage collection, you need to delete any memory you no longer need.