When we learn dynamic allocation in c++, the simplest example about delete[] is :
int main()
{
size_t n = 5;
int *p = new int[n];
delete[] p;
}
In plain English delete[] is able to delete an C-like array from the heap memory which is previously allocated by the new. However, i'm getting errors for the following code.
int main()
{
size_t n = 5;
int *p = new int[n];
p++; //move the pointer to the second element of the array
delete[] p;
}
I was thinking if this could delete the same heap memory, but from the second element onwards. however, i'm getting some error which i dont understand:
Test Prep(51600,0x1000d1dc0) malloc: *** error for object 0x100537134: pointer being freed was not allocated
It's simply undefined behaviour to delete a pointer that's not allocated by new. Undefined behaviour doesn't necessarily give any errors!
You're changing the pointer to point to the next element - which isn't what new returned.
There's no way to partially delete as you wanted. You should look at containers such as std::vector which supports (and manages the allocations) such partial deletion/resizing.
Related
If i define array in the next way:
char** array=new char*[3];
and I initialize the array like that for example:
for(int i=0; i<3;i++){
array[i]=new char[5];
}
and after that, I doing:
delete[] array;
What happens during the delete?
This causes a memory leak: Only memory of array is freed, but memory reserved for cells is not freed before your program closes.
You should match each new with a delete:
for(int i=0; i<3;i++){
delete[] array[i];
}
delete[] array;
If you received the pointer from some function, you need to know its size to be able to free all the memory.
To avoid manual memory handling, you can either use vector of shared pointers (std::vector<std::shared_ptr<char>) or in this specific case, use strings (std::vector<std::string>).
Here is a simple program using dynamic memory.
My question is do I have to delete the memory at the and or the struct will take care of it for me?
#include <iostream>
struct Student {
int grade;
char *name;
};
void print(Student name);
int main() {
Student one;
one.grade = 34;
one.name = new char[12];
int i;
for (i = 0; i < 11; ++i) {
one.name[i] = 'a' + i;
}
one.name[i] = '\0';
print(one);
delete[] one.name;
return 0;
}
void print(Student name) {
std::cout << name.name << " has a score of " << name.grade << "\n";
}
There is a simple rule of thumb- for each call of new you should have one call of delete. In this case you should delete one.name like so : delete [] one.name.
Of course you should do that after you no longer need its value. In this case this is immediately before the return.
Memory allocated dynamically using new or malloc must be freed up when you're done with it using delete or free otherwise you'll get Memory leak.
Make difference between delete and delete[]: the first without subscript operator is used to deleted dynamic memory allocated with new for a pointer. The latter is used for deleting an array allocated dynamically.
So in your case:
one.name = new char[12]; // an array of 12 elements in the heap
delete[] one.name; // freeing up memory
char* c = new char('C'); // a single char in the heap
delete c;
Don't mix new, delete with malloc, free:
This is undefined behavior, as there's no way to reliably prove that memory behind the pointer was allocated correctly (i.e. by new for delete or new[] for delete[]). It's your job to ensure things like that don't happen. It's simple when you use right tools, namely smart pointers. Whenever you say delete, you're doing it wrong.
If you don't want to use unique/shared pointers, you could use a constructor for allocating and a destructor for automatically freeing memory.
If the raw pointer in your structure is an observing pointer, you don't have to delete the memory (of course, someone somewhere in the code must release the memory).
But, if the raw pointer is an owning pointer, you must release it.
In general, every call to new[] must have a matching call to delete[], else you leak memory.
In your code, you invoked new[], so you must invoke delete[] to properly release the memory.
In C++, you can avoid bug-prone leak-prone raw pointers, and use smart pointers or container classes (e.g. std::vector, std::string, etc.) instead.
Creating a Structure does not mean it will handle garbage collection in C++
there is no garbage collection so for every memory you allocate by using new you should use delete keyword to free up space. If you write your code in JAVA you wont have to delete as garbage collector will automatically delete unused references.
Actually the structure won't freeup or delete the memory that you have been created. if in case you want to freeup the space you can do as follows.
#include <iostream>
using namespace std;
int main()
{
char *c = new char[12];
delete[] c;
return(0);
}
I'm catching up on pointers. I wrote down a few lines of code to test the different ways I could dynamically allocate a 2d array (posted at the bottom)
My questions are the following:
Should I use malloc in c++, or new? If I use new, can I still use realloc?
When should I use realloc? What are the implications of using it in terms of performance and bugs?
Out of the examples bellow, which objectNew version should I use? If the answer depends on the application, what are does it depend on?
Many thanks,
Matt
#include <stdio.h>
#include <stdlib.h>
struct myObject
{
int data;
myObject(int i)
{
data = i;
}
myObject()
{
data = 0;
}
};
int main(){
int r = 7;
int c = 6;
printf("Objects using NEW===============================\n");
//notice the triple pointer being assigned a new double pointer array
myObject*** objectNew = new myObject** [r];
for(int i=0;i<r;i++)
{
//objectNew is a 1D array of double pointers, however if we assign another layer of pointers, it becomes a 2D array of pointers to myObject
objectNew[i] = new myObject* [c];
for(int j=0;j<c;j++){
objectNew[i][j] = new myObject(10*i+j);
//notice that we dereference data (->)
printf("objectNew[%2d][%2d]=%02d\n",i,j,objectNew[i][j]->data);
}
}
delete objectNew;
printf("Objects using NEW version 2===============================\n");
//notice the triple pointer being assigned a new double pointer array
myObject** objectNew2 = new myObject* [r];
for(int i=0;i<r;i++)
{
//objectNew is a 1D array of double pointers, however if we assign another layer of pointers, it becomes a 2D array of pointers to myObject
objectNew2[i] = new myObject [c];
for(int j=0;j<c;j++){
objectNew2[i][j] = myObject(10*i+j);
//notice that we dereference data (->)
printf("objectNew2[%2d][%2d]=%02d\n",i,j,objectNew2[i][j].data);
}
}
delete objectNew2;
printf("Objects using MALLOC===============================\n");
//notice the double pointer being allocated double pointers the size of pointers to myObject
myObject** objectMalloc =(myObject**) malloc(sizeof(myObject*)*r);
for(int i=0;i<r;i++)
{
//now we are assigning array of pointers the size of myObject to each double pointer
objectMalloc[i] = (myObject*) malloc(sizeof(myObject)*c);
for(int j=0;j<c;j++){
objectMalloc[i][j] = myObject(10*i+j);
//notice that we access data without dereferencing (.)
printf("objectMalloc[%2d][%2d]=%02d\n",i,j,objectMalloc[i][j].data);
}
}
free((void*) objectMalloc);
//same as Malloc
printf("Objects using CALLOC===============================\n");
myObject** objectCalloc = (myObject**) calloc(r,sizeof(myObject*));
for(int i=0;i<r;i++)
{
objectCalloc[i] = (myObject*) calloc(c,sizeof(myObject));
for(int j=0;j<c;j++){
objectCalloc[i][j] = myObject(10*i+j);
printf("objectCalloc[%2d][%2d]=%02d\n",i,j,objectCalloc[i][j].data);
}
}
free((void*) objectCalloc);
printf("Int using NEW===============================\n");
//int is not an object
int** intNew = new int* [r];
for(int i=0;i<r;i++)
{
intNew[i] = new int[c];
for(int j=0;j<c;j++){
intNew[i][j] = 10*i+j;
printf("intNew[%2d][%2d]=%02d\n",i,j,intNew[i][j]);
}
}
delete intNew;
printf("Int using malloc===============================\n");
int** intMalloc =(int**) malloc(sizeof(int*)*r);
for(int i=0;i<r;i++)
{
intMalloc[i] =(int*) malloc(sizeof(int)*c);
for(int j=0;j<c;j++){
intMalloc[i][j] = 10*i+j;
printf("intMalloc[%2d][%2d]=%02d\n",i,j,intMalloc[i][j]);
}
}
free((void*) intMalloc);
getchar();
return 0;
}
new and new[] are constructor aware, the C memory allocation functions are not.
Similarly, delete and delete [] are destructor aware, whereas free isn't.
realloc does not work with memory allocated with new, there is no standards defined analog to the realloc function with C++ memory management functions.
Do not mix new and delete with malloc/calloc/realloc and free (i.e. don't free any memory allocated with new, don't delete any memory allocated with malloc)
If you are doing new [], you most likely should be using an std::vector, which encapsulates all that memory management for you.
If you are using memory allocated raw pointers, you might be better served using smart/semi-smart pointers like boost::shared_ptr or boost::scoped_ptr or std::auto_ptr, depending on your needs.
Thanks to David Thornley for bringing this up:
Never mix scalar new and delete with their array forms, i.e. don't delete[] memory allocated with new, and don't delete memory allocated with new[]. Undefined behavior all around.
In your example, you SHOULD use new and new[] if you must, because as I said, they are constructor aware, and your class is not a POD data type since it has a constructor.
Please see the C++ FAQ for more information:
C++ FAQ Freestore Management
1) Should I use malloc in c++, or new?
If I use new, can I still use realloc?
Use new. And never use realloc with new.
When should I use realloc? What are
the implications of using it in terms
of performance and bugs?
Instead of using realloc, I usually implement my own memory-pool, from which I reallocate memory when I need it. This also improves performance.
Should I use malloc in c++, or new? If
I use new, can I still use realloc?
You can use malloc in C++; however, it is strongly discouraged in most circumstances. Additionally, if you call malloc, calloc, realloc, etc., you need to use free to deallocate the memory when done.
If you use new to allocate memory, you must use delete to deallocate it.
The C-allocation routines do not have type safety. new does.
If you want to write C++ (!!) programs don't use malloc, realloc, free. It is just not C++ functions.
And there is no necessity to use new is your cases (I'm talking about the example).
You should use vector or some other containter.
In general, you should try to avoid doing your own memory allocation in C++. Most (not all) arrays can be done with std::vector better than you're going to do your own, particularly since you are making a mistake here.
You allocate, say, intNew and intNew[i]. Then you delete [] intNew; (the brackets are necessary here, leaving them off is an error), without delete []ing any of the intNew[i]. The one-dimensional arrays you allocated are now memory leaks, and cannot possibly be freed because you've lost all references to them. Neither C nor C++ normally come with a garbage collector.
The C memory allocation functions deal with memory only. They aren't type-safe, and don't call constructors or destructors. They can be used with data types that require neither, but you do have to make sure they do neither. (It is possible to malloc memory and use placement new to create objects there, but that's more advanced.)
The C++ memory allocation functions deal with memory and objects. They are type-safe, mostly, and do call constructors and destructors. Not all objects can be moved safely, so there is no equivalent of malloc. The tricky part is that you have to match new with delete, and new[] with delete[]. You have this error in your code: delete intNew; should be delete [] intNew;.
following a discussion in a software meeting I've set out to find out if deleting a dynamically allocated, primitives array with plain delete will cause a memory leak.
I have written this tiny program and compiled it with visual studio 2008 running on windows XP:
#include "stdafx.h"
#include "Windows.h"
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*1000; i++)
{
int* p = new int[1024*100000];
for (int j =0;j<BLOCK_SIZE;j++) p[j]= j % 2;
Sleep(1000);
delete p;
}
}
I than monitored the memory consumption of my application using task manager, surprisingly the memory was allocated and freed correctly, allocated memory did not steadily increase as was expected
I've modified my test program to allocate a non primitive type array :
#include "stdafx.h"
#include "Windows.h"
struct aStruct
{
aStruct() : i(1), j(0) {}
int i;
char j;
} NonePrimitive;
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*100000; i++)
{
aStruct* p = new aStruct[1024*100000];
Sleep(1000);
delete p;
}
}
after running for for 10 minutes there was no meaningful increase in memory
I compiled the project with warning level 4 and got no warnings.
is it possible that the visual studio run time keep track of the allocated objects types so there is no different between delete and delete[] in that environment ?
delete p, where p is an array is called undefined behaviour.
Specifically, when you allocate an array of raw data types (ints), the compiler doesnt have a lot of work to do, so it turns it into a simple malloc(), so delete p will probably work.
delete p is going to fail, typically, when:
p was a complex data type - delete p; won't know to call individual destructors.
a "user" overloads operator new[] and delete[] to use a different heap to the regular heap.
the debug runtime overloads operator new[] and delete[] to add extra tracking information for the array.
the compiler decides it needs to store extra RTTI information along with the object, which delete p; won't understand, but delete []p; will.
No, it's undefined behavior. Don't do it - use delete[].
In VC++ 7 to 9 it happens to work when the type in question has trivial destructor, but it might stop working on newer versions - usual stuff with undefined behavior. Don't do it anyway.
It's called undefined behaviour; it might work, but you don't know why, so you shouldn't stick with it.
I don't think Visual Studio keeps track of how you allocated the objects, as arrays or plain objects, and magically adds [] to your delete. It probably compiles delete p; to the same code as if you allocated with p = new int, and, as I said, for some reason it works. But you don't know why.
One answer is that yes, it can cause memory leaks, because it doesn't call the destructor for every item in the array. That means that any additional memory owned by items in the array will leak.
The more standards-compliant answer is that it's undefined behaviour. The compiler, for example, has every right to use different memory pools for arrays than for non-array items. Doing the new one way but the delete the other could cause heap corruption.
Your compiler may make guarantees that the standard doesn't, but the first issue remains. For POD items that don't own additional memory (or resources like file handles) you might be OK.
Even if it's safe for your compiler and data items, don't do it anyway - it's also misleading to anyone trying to read your code.
no, you should use delete[] when dealing with arrays
Just using delete won't call the destructors of the objects in the array. While it will possibly work as intended it is undefined as there are some differences in exactly how they work. So you shouldn't use it, even for built in types.
The reason seems not to leak memory is because delete is typically based on free, which already knows how much memory it needs to free. However, the c++ part is unlikely to be cleaned up correctly. I bet that only the destructor of the first object is called.
Using delete with [] tells the compiler to call the destructor on every item of the array.
Not using delete [] can cause memory leaks if used on an array of objects that use dynamic memory allocations like follows:
class AClass
{
public:
AClass()
{
aString = new char[100];
}
~AClass()
{
delete [] aString;
}
private:
const char *aString;
};
int main()
{
AClass * p = new AClass[1000];
delete p; // wrong
return 0;
}
I am wondering about the delete[] operator in C++. (I am using Visual Studio 2005).
I have an unmanaged DLL that is being called by a managed DLL. When I close this program after performing a few tasks while debugging, I am getting many (thousands?) of memory leaks, mostly 24 bytes - 44 bytes in size.. I suspect it might be due to a certain unmanaged DLL I have.
Anyway, from what I understand, if I have the following code:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up correctly, am I right?
What happens when I have the following code:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is deleted right? So it means that pointerIt is now not pointing to valid memory.. But that's ok because I can set both pointers to NULL, right?
Anyway, what happens now if I do this:
char* pointerFirstPosition = new char[500];
char* pointerIt = pointerFirstPosition;
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointerIt; // delete the pointer iterator...
Will this code delete the memory block pointed to by pointerIt up to pointerIt +500? or will it delete the memory block pointed to by pointerFirstPos to pointerFirstPos +500?
Could this result in a memory leak?
Sorry for the long winded message, I'm trying to get my message across clearly.
Thanks,
kreb
First question set:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up
correctly, am I right?
right.
Second question set:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is
deleted right? So it means that
pointerIt is now not pointing to valid
memory.. But that's ok because I can
set both pointers to NULL, right?
The memory pointer holds an address to is fully delted yes. Both pointer and pointerIt hold an address to invalid memory. Each pointer is simply a variable, and every variable is independent. So both store their own address independent of each other. The dereference operator * will simply give you the variable at that address. The variable at that address is a different variable than the pointer variable.
Third question set:
You should be deleting only the address that was allocated, the whole array. You'll have undefined results if you try to delete a partial array. Could it result in a memory leak? Possibly, could it result in a crash? Possibly, could it result in ....? Possibly.
So only delete what you allocate. If you allocate an array then you delete with delete[] if you delete a type that is not an array you delete with delete.
Here is an eample of something that is fine just for clarity:
char* pointer = new char[500];
char* pointerIt = pointer;
//This is fine because you are deleting the same address:
delete[] pointerIt;
//The memory that both variables point to is freed, do not try to free again
check out boost::shared_ptr or boost::scoped_ptr and NEVER worry about this again.
This gives you a static & reference counted way to manage your memory.
http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm