int *p=(int * )malloc(sizeof(int));
delete p;
When we allocate memory using malloc then we should release it using free and when we allocate using new in C++ then we should release it using delete.
But if we allocate memory using malloc and then use delete, then there should be some error. But in the above code there's no error or warning coming in C++.
Also if we reverse and allocate using new and release using free, then also there's no error or warning.
Why is it so?
This is undefined behaviour, 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.
then there should be some error
There is. It is just not necessarily apparent.
The C++ standard (and the C standard, on which the C++ standard is modeled) call this kind of error undefined behavior. By undefined they mean that anything at all may happen. The program may continue normally, it may crash immediately, it may produce a well-defined error message and exit gracefully, it may start exhibiting random errors at some time after the actual undefined behavior event, or invoke nasal demons.
It is your responsibility to watch out and eliminate these errors. Nothing is guaranteed to alert you when they happen.
Use free() not delete.
if you malloc you then have to call free to free memory.
if you new you have to call delete to free memory.
Here is a link that explains it.
Related
I am using this in a void:
unsigned char *nEncodedBytes = NULL;
nEncodedBytes = new unsigned char[m_lLenCompressedBytes];
short *shrtDecoded = NULL;
shrtDecoded = new short[iCountDecodedShorts];
short *m_ShortOut;
m_ShortOut = (short*)malloc(( 960*6)*sizeof(short));
unsigned char *m_DataBytes;
m_DataBytes = (unsigned char*)calloc((960*6),sizeof(char));
When I am done, I free the memory using
delete (nEncodedBytes);
delete (shrtDecoded);
free(m_DataBytes);
free(m_ShortOut);
Is this fine? I am unsure why I was using delete in one place, and free in the other.
I copied my code around.
Is there a memory leak?
Thank you.
You use free when you use malloc. In all likelihood, you shouldn't be using malloc at all in C++; it's the C way of doing things and only rarely wanted in C++.
You use delete when you allocate with new. new calls the constructor as well as allocating memory, and delete calls the destructor as well as releasing memory. These are thus the object orientated C++ options. There is, however, a wrinkle. Because the implementation of C++ doesn't know whether a pointer refers to an array or a single object if you allocate an array (e.g. nEncodedBytes = new unsigned char[m_lLenCompressedBytes];) then you should use delete[] instead of delete to release it.
Mind you, failing to call delete[] only means that you will only call the destructor for the first object in an array so, in this particular case there should be no difference in the outcome between calling delete[] and calling delete because char has no destructor.
I don't see a memory leak in your code but since you haven't posted all your code we can't tell.
You should use
delete [] nEncodedBytes;
delete [] shrtDecoded;
as you are deleting arrays.
Don't mix malloc and new (first because of stylistic reasons, and then because you should never delete a malloc-ed memory or free a new-ed zone). Consider using standard C++ containers. You won't even need to explicitly allocate memory (the library will do that for you).
You could code
std::vector<char> nEncodedBytes;
nEncodedBytes.resize(encodedbyteslen);
On Linux, use valgrind to hunt memory leaks. BTW, you might be interested by Boehm's GC, perhaps using its allocator like here.
BTW, when using yourself malloc you should always test its result, at least like
SomeType* ptr = malloc(sizeof(SomeType));
if (!ptr) { perror("malloc SomeType"); exit(EXIT_FAILURE); };
remember that malloc could fail. You may want to limit the memory available (e.g. with ulimit -m in bash in your terminal) for testing purposes (e.g. to make malloc -or new- fail more easily to ensure you handle that kind of failure well enough).
Is this fine?
Not quite. There are a couple problems. One -- your troublesome use of free -- we'll address in a moment. But first, your use of new[] with delete (non-[]) invokes Undefined Behavior:
Here you are using new []:
nEncodedBytes = new unsigned char[m_lLenCompressedBytes];
And here you are using delete:
delete (nEncodedBytes);
This should be:
delete [] nEncodedBytes;
Using the [] for of new with the non-[] form of delete invokes Undefined Behavior. Now in reality, all the compilers & platforms I'm aware of will handle this fine and do what you expect in this particular case -- but you should never rely on Undefined Behavior.
Now for your use of malloc and free:
I am unsure why I was using delete in one place, and free in the
other.
You probably shouldn't be. Here's a rule of thumb:
In C++, always use new and delete; never use malloc and free.
Yes, there are exceptions, but they are first of all rare, and second of all you will know exactly when the exceptions come in to play. In the example you've posted here, I see no reason that compels the use of malloc and free. Hence, you should not be.
Contrary to (popular?) belief, mixing new/delete and malloc/free in a single C++ program does no in itself invoke Undefined Behavior or make your program otherwise ill-formed. You can do it, if you do it properly. But you still shouldn't.
Is there a memory leak?
Well, since you have invoked Undefined Behavior, there could be. Undefined Behavior means anything can happen. You are however de-allocating everything you allocate in the code shown. So aside from the UB, I see no memory leak here.
I was just thinking what happens when we use free() with new in C++.
In case if we use free() with new then the memory could be freed. Its just the destructor will not be called. Leaving behavior something like similar to dangling pointer.
I understand that above we should not use free() with new as it may corrupt the heap.
But then also I would like to visualize the behavior conceptually.
Using free on memory allocated by new is undefined behavior. There's no guarantee that new returns an address returned from malloc. (In fact, new[] often doesn't.)
You're not supposed to mix these at all. new and delete are paired up just as malloc and free are.
Remember that the behavior of new can be completely re-defined by the application and can use an allocation strategy that has nothing to do with the heap at all. It's because of this that you can't depend on free to be able to do anything at all with pointers generated by new. They're two different worlds.
I know free() won't call the destructor, but what else will this cause besides that the member variable won't be destructed properly?
Also, what if we delete a pointer that is allocated by malloc?
It is implementation defined whether new uses malloc under the hood. Mixing new with free and malloc with delete could cause a catastrophic failure at runtime if the code was ported to a new machine, a new compiler, or even a new version of the same compiler.
I know free() won't call the destructor
And that is reason enough not to do it.
In addition, there's no requirement for a C++ implementation to even use the same memory areas for malloc and new so it may be that you're trying to free memory from a totally different arena, something which will almost certainly be fatal.
Many points:
It's undefined behaviour, and hence inherently risky and subject to change or breakage at any time and for no reason at all.
(As you know) delete calls the destructor and free doesn't... you may have some POD type and not care, but it's easy for someone else to add say a string to that type without realising there are weird limitations on its content.
If you malloc and forget to use placement new to construct an object in it, then invoke a member function as if the object existed (including delete which calls the destructor), the member function may attempt operations using pointers with garbage values
new and malloc may get memory from different heaps.
Even if new calls malloc to get its memory, there may not be a 1:1 correspondence between the new/delete and underlying malloc/free behaviour.
e.g. new may have extra logic such as small-object optimisations that have proven beneficial to typical C++ programs but harmful to typical C programs.
Someone may overload new, or link in a debug version of malloc/realloc/free, either of which could break if you're not using the functions properly.
Tools like ValGrind, Purify and Insure won't be able to differentiate between the deliberately dubious and the accidentally.
In the case of arrays, delete[] invokes all the destructors and free() won't, but also the heap memory typically has a counter of the array size (for 32-bit VC++2005 Release builds for example, the array size is in the 4 bytes immediately before the pointer value visibly returned by new[]. This extra value may or may not be be there for POD types (not for VC++2005), but if it is free() certainly won't expect it. Not all heap implementations allow you to free a pointer that's been shifted from the value returned by malloc().
An important difference is that new and delete also call the constructor and destructor of the object. Thus, you may get unexpected behavior. That is the most important thing i think.
Because it might not be the same allocator, which could lead to weird, unpredictable behaviour. Plus, you shouldn't be using malloc/free at all, and avoid using new/delete where it's not necessary.
It totally depends on the implementation -- it's possible to write an implementation where this actually works fine. But there's no guarantee that the pool of memory new allocates from is the same pool that free() wants to return the memory to. Imagine that both malloc() and new use a few bytes of extra memory at the beginning of each allocated block to specify how large the block is. Further, imagine that malloc() and new use different formats for this info -- for example, malloc() uses the number of bytes, but new uses the number of 4-byte long words (just an example). Now, if you allocate with malloc() and free with delete, the info delete expects won't be valid, and you'll end up with a corrupted heap.
I am working on modifying a relatively large C++ program, where unfortunately it is not always clear whether someone before me used C or C++ syntax (this is in the electrical engineering department at a university, and we EEs are always tempted to use C for everything, and unfortunately in this case, people can actually get away with it).
However, if someone creates an object:
Packet* thePacket = new Packet();
Does it matter whether it is destroyed with delete thePacket; or free(thePacket); ?
I realize that delete calls the destructor while free() does not, but Packet does not have a destructor. I am having a terrible time stuck in a memory management swamp here and I'm thinking this may be one of the many problems.
Yes it does matter.
For memory obtained using new you must use delete.
For memory obtained using malloc you must use free.
new and malloc may use different data structures internally to keep track of what and where it has allocated memory. So in order to free memory, you have to call that corresponding function that knows about those data structures. It is however generally a bad idea to mix these two types of memory allocation in a piece of code.
If you call free(), the destructor doesn't get called.
Also, there's no guarantee that new and free operate on the same heap.
You can also override new and delete to operate specially on a particular class. If you do so, but call free() instead of the custom delete, then you miss whatever special behavior you had written into delete. (But you probably wouldn't be asking this question if you had done that, because you'd know what behaviors you were missing..)
Packet has a destructor, even if you haven't explicitly declared one. It has a default destructor. The default destructor probably doesn't actually do much, but you can't count on that being the case. It's up to the compiler what it does.
new and malloc also may have wildly different implementations. For example, delete is always called in a context where it has perfect information about the size of the data structure it's deleting at compile time. free does not have this luxury. It's possible that the allocator that new is using may not store the bytes at the beginning of the memory area stating how many bytes it occupies. This would lead free to do entirely the wrong thing and crash your program when freeing something allocated with new.
Personally, if getting people to do the right thing or fixing the code yourself is completely impossible, I would declare my own global operator new that called malloc so then free would definitely not crash, even though it would still not call the destructor and be generally really ugly.
In short, it is as bad as undefined behavior.
This is quiet self explanatory.
C Standard ($7.20.3.2/2) - "The free
function causes the space pointed to
by ptr to be deallocated, that is,
made available for further allocation.
If ptr is a null pointer, no action
occurs. Otherwise, if the argument
does not match a pointer earlier
returned by the calloc, malloc, or
realloc function, or if the space has
been deallocated by a call to free or
realloc, the behavior is undefined."
You are absolutely right, it is NOT correct. As you said yourself, free won't call the destructor. Even if Packet doesn't have an explicit destructor, it's using an inherited one.
Using free on an object created with new is like destroying only what a shallow-copy would reach. Deep-destroying NEEDS the destructor function.
Also, I'm not sure objects created with new() are on the same memory map as malloc()'d memory. They are not guaranteed to be, I think.
if someone creates an object:
Packet* thePacket = new Packet();
Does it matter whether is is destroyed with delete thePacket; or free(thePacket); ?
Yes it does matter. free (thePacket) would invoke Undefined Behaviour but delete thePacket would not and we all know Undefined Behaviour may have disastrous consequences.
This question was asked to me in an interview:
In C++,
what if we allocate memory using malloc and use delete to free that allocated memory?
what if we allocate the memory using new and free it using free?
What are the problems that we would face if the above things are used in the code?
My answer was there is no difference. Was I right in saying so?
If you do so you will run into undefined behavior. Never try that. Although new might be implemented through malloc() and delete might be implemented through free() there's no guarantee that they are really implemented that way and also the user can overload new and delete at his discretion. You risk running into heap corruption.
Other than that don't forget that when you call malloc() you get raw memory - no constructor is invoked - and when you call free() no destructor is invoked. This can as well lead to undefined behavior and improper functioning of the program.
The bottom line is... never do this.
1) Undefined behaviour but will probably "work" though. Destructors will get called on the memory being freed that pobably doesn't want to be deconstructed.
2) Undefined behaviour but will probably "work" though. Destructors will NOT get called.
ie IF it works, and there is no guarantee of that, then it will only, likely, work exactly as required for basic builtin data types.