new, delete ,malloc & free - c++

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.

Related

What happens when delete pointer to stack object? [duplicate]

Ignoring programming style and design, is it "safe" to call delete on a variable allocated on the stack?
For example:
int nAmount;
delete &nAmount;
or
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
No, it is not safe to call delete on a stack-allocated variable. You should only call delete on things created by new.
For each malloc or calloc, there should be exactly one free.
For each new there should be exactly one delete.
For each new[] there should be exactly one delete[].
For each stack allocation, there should be no explicit freeing or deletion. The destructor is called automatically, where applicable.
In general, you cannot mix and match any of these, e.g. no free-ing or delete[]-ing a new object. Doing so results in undefined behavior.
Well, let's try it:
jeremy#jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy#jeremy-desktop:~$ g++ -o test test.cpp
jeremy#jeremy-desktop:~$ ./test
Segmentation fault
So apparently it is not safe at all.
Keep in mind that when you allocate a block of memory using new (or malloc for that matter), the actual block of memory allocated will be larger than what you asked for.
The memory block will also contain some bookkeeping information so that when you free the block, it can easily be put back into the free pool and possibly be coalesced with adjacent free blocks.
When you try to free any memory that you didn't receive from new, that bookkeeping information wont be there but the system will act like it is and the results are going to be unpredictable (usually bad).
Yes, it is undefined behavior: passing to delete anything that did not come from new is UB:
C++ standard, section 3.7.3.2.3:
The value of the first argument supplied to one of thea deallocation functions provided in the standard library may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call to the deallocation function has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_t&) in the standard library.
The consequences of undefined behavior are, well, undefined. "Nothing happens" is as valid a consequence as anything else. However, it's usually "nothing happens right away": deallocating an invalid memory block may have severe consequences in subsequent calls to the allocator.
After playing a bit with g++ 4.4 in windows, I got very interesting results:
calling delete on a stack variable doesn't seem to do anything. No errors throw, but I can access the variable without problems after deletion.
Having a class with a method with delete this successfully deletes the object if it is allocated in the heap, but not if it is allocated in the stack (if it is in the stack, nothing happens).
Nobody can know what happens. This invokes undefined behavior, so literally anything can happen. Don't do this.
No,
Memory allocated using new should be deleted using delete operator
and that allocated using malloc should be deleted using free.
And no need to deallocate the variable which are allocated on stack.
An angel loses its wings... You can only call delete on a pointer allocated with new, otherwise you get undefined behavior.
here the memory is allocated using stack so no need to delete it exernally but if you have allcoted dynamically
like
int *a=new int()
then you have to do delete a and not delete &a(a itself is a pointer), because the memory is allocated from free store.
You already answered the question yourself. delete must only be used for pointers optained through new. Doing anything else is plain and simple undefined behaviour.
Therefore there is really no saying what happens, anything from the code working fine through crashing to erasing your harddrive is a valid outcome of doing this. So please never do this.
It's UB because you must not call delete on an item that has not been dynamically allocated with new. It's that simple.
Motivation: I have two objects, A and B. I know that A has to be instantiated before B, maybe because B needs information calculated by A. Yet, I want to destruct A before B. Maybe I am writing an integration test, and I want server A to shut-down first. How do I accomplish that?
A a{};
B b{a.port()};
// delete A, how?
Solution: Don't allocate A on the stack. Instead, use std::make_unique and keep a stack-allocated smart pointer to a heap-allocated instance of A. That way is the least messy option, IMO.
auto a = std::make_unique<A>();
B b{a->port()};
// ...
a.reset()
Alternatively, I considered moving the destruction logic out of A's destructor and calling that method explicitly myself. The destructor would then call it only if it has not been called previously.

Do we have a concept of dangling object in C++

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.

Behaviour of malloc with delete in C++

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.

Why can't we free() memory that was allocated by new?

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.

C++ object created with new, destroyed with free(); How bad is this?

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.